aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml56
-rw-r--r--.tx/config2
-rw-r--r--Makefile.am2
-rw-r--r--REVIEWERS123
-rw-r--r--SECURITY.md2
-rw-r--r--build-aux/m4/ax_boost_base.m414
-rw-r--r--build-aux/m4/l_atomic.m45
-rw-r--r--build_msvc/README.md20
-rw-r--r--build_msvc/bitcoin_config.h.in4
-rw-r--r--build_msvc/common.init.vcxproj.in4
-rw-r--r--build_msvc/libsecp256k1_config.h17
-rwxr-xr-xbuild_msvc/msvc-autogen.py4
-rwxr-xr-xci/lint/06_script.sh12
-rwxr-xr-xci/test/00_setup_env_native_asan.sh11
-rwxr-xr-xci/test/00_setup_env_native_fuzz_with_valgrind.sh2
-rwxr-xr-xci/test/00_setup_env_native_qt5.sh2
-rwxr-xr-xci/test/00_setup_env_native_tidy.sh2
-rwxr-xr-xci/test/00_setup_env_native_valgrind.sh2
-rwxr-xr-xci/test/04_install.sh8
-rwxr-xr-xci/test/05_before_script.sh4
-rwxr-xr-xci/test/06_script_a.sh7
-rwxr-xr-xci/test/06_script_b.sh24
-rwxr-xr-xci/test/wrap-qemu.sh2
-rwxr-xr-xci/test/wrap-wine.sh2
-rw-r--r--configure.ac79
-rw-r--r--contrib/builder-keys/keys.txt1
-rw-r--r--contrib/devtools/iwyu/bitcoin.core.imp1
-rwxr-xr-xcontrib/devtools/symbol-check.py6
-rw-r--r--contrib/guix/INSTALL.md4
-rw-r--r--contrib/guix/README.md2
-rwxr-xr-xcontrib/guix/libexec/build.sh8
-rw-r--r--contrib/guix/manifest.scm107
-rw-r--r--contrib/guix/patches/elfsteem-value-error-python-39.patch13
-rw-r--r--contrib/guix/patches/gcc-10-remap-guix-store.patch25
-rw-r--r--contrib/guix/patches/glibc-2.24-guix-prefix.patch25
-rw-r--r--contrib/guix/patches/glibc-2.27-guix-prefix.patch25
-rw-r--r--contrib/guix/patches/lief-fix-ppc64-nx-default.patch29
-rw-r--r--contrib/guix/patches/nsis-disable-installer-reloc.patch30
-rw-r--r--contrib/macdeploy/README.md2
-rwxr-xr-xcontrib/message-capture/message-capture-parser.py3
-rwxr-xr-xcontrib/seeds/makeseeds.py7
-rw-r--r--contrib/seeds/nodes_main.txt1502
-rw-r--r--contrib/seeds/nodes_main_manual.txt77
-rw-r--r--contrib/seeds/nodes_test.txt99
-rwxr-xr-xcontrib/signet/getcoins.py2
-rwxr-xr-xcontrib/signet/miner111
-rw-r--r--contrib/valgrind.supp21
-rw-r--r--contrib/verify-commits/trusted-keys2
-rw-r--r--depends/config.site.in15
-rw-r--r--depends/hosts/darwin.mk3
-rw-r--r--depends/hosts/default.mk3
-rw-r--r--depends/hosts/linux.mk4
-rw-r--r--depends/hosts/mingw32.mk4
-rw-r--r--depends/hosts/netbsd.mk4
-rw-r--r--depends/packages/bdb.mk2
-rw-r--r--depends/packages/expat.mk8
-rw-r--r--depends/packages/libevent.mk3
-rw-r--r--depends/packages/libxcb.mk3
-rw-r--r--depends/packages/libxkbcommon.mk5
-rw-r--r--depends/packages/native_cctools.mk14
-rw-r--r--depends/packages/native_clang.mk3
-rw-r--r--depends/packages/native_ds_store.mk2
-rw-r--r--depends/packages/native_libtapi.mk4
-rw-r--r--depends/packages/native_mac_alias.mk2
-rw-r--r--depends/packages/qt.mk53
-rw-r--r--depends/patches/libxcb/remove_pthread_stubs.patch12
-rw-r--r--depends/patches/qt/dont_hardcode_x86_64.patch4
-rw-r--r--depends/patches/qt/fast_fixed_dtoa_no_optimize.patch20
-rw-r--r--depends/patches/qt/fix_android_jni_static.patch2
-rw-r--r--depends/patches/qt/fix_limits_header.patch33
-rw-r--r--depends/patches/qt/guix_cross_lib_path.patch17
-rw-r--r--doc/README.md1
-rw-r--r--doc/bips.md4
-rw-r--r--doc/bitcoin-conf.md2
-rw-r--r--doc/build-netbsd.md122
-rw-r--r--doc/build-osx.md8
-rw-r--r--doc/build-unix.md38
-rw-r--r--doc/dependencies.md2
-rw-r--r--doc/descriptors.md10
-rw-r--r--doc/design/assumeutxo.md4
-rw-r--r--doc/developer-notes.md21
-rw-r--r--doc/i2p.md26
-rw-r--r--doc/man/bitcoin-cli.1182
-rw-r--r--doc/man/bitcoin-qt.1819
-rw-r--r--doc/man/bitcoin-tx.1146
-rw-r--r--doc/man/bitcoin-util.166
-rw-r--r--doc/man/bitcoin-wallet.1122
-rw-r--r--doc/man/bitcoind.1797
-rw-r--r--doc/managing-wallets.md27
-rw-r--r--doc/policy/README.md2
-rw-r--r--doc/policy/mempool-replacements.md7
-rw-r--r--doc/policy/packages.md4
-rw-r--r--doc/release-notes-15936.md15
-rw-r--r--doc/release-notes-24098.md22
-rw-r--r--doc/release-notes-24118.md10
-rw-r--r--doc/release-notes-24198.md6
-rw-r--r--doc/release-notes-24494.md2
-rw-r--r--doc/release-notes-empty-template.md99
-rw-r--r--doc/release-notes.md309
-rw-r--r--doc/release-notes/release-notes-24408.md5
-rw-r--r--share/examples/bitcoin.conf686
-rw-r--r--share/setup.nsi.in9
-rw-r--r--src/.clang-tidy15
-rw-r--r--src/Makefile.am62
-rw-r--r--src/Makefile.bench.include12
-rw-r--r--src/Makefile.leveldb.include1
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.qt_locale.include7
-rw-r--r--src/Makefile.qttest.include2
-rw-r--r--src/Makefile.test.include36
-rw-r--r--src/Makefile.test_fuzz.include3
-rw-r--r--src/Makefile.test_util.include2
-rw-r--r--src/addrdb.cpp4
-rw-r--r--src/addrman.cpp151
-rw-r--r--src/addrman.h26
-rw-r--r--src/addrman_impl.h42
-rw-r--r--src/banman.cpp8
-rw-r--r--src/bench/addrman.cpp2
-rw-r--r--src/bench/checkblock.cpp1
-rw-r--r--src/bench/coin_selection.cpp7
-rw-r--r--src/bench/descriptors.cpp30
-rw-r--r--src/bench/gcs_filter.cpp79
-rw-r--r--src/bench/wallet_loading.cpp74
-rw-r--r--src/bitcoin-chainstate.cpp54
-rw-r--r--src/bitcoin-cli.cpp6
-rw-r--r--src/bitcoin-tx.cpp5
-rw-r--r--src/bitcoin-util.cpp2
-rw-r--r--src/bitcoin-wallet.cpp2
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/blockfilter.cpp28
-rw-r--r--src/blockfilter.h17
-rw-r--r--src/chain.cpp62
-rw-r--r--src/chain.h42
-rw-r--r--src/chainparams.cpp42
-rw-r--r--src/chainparamsseeds.h1174
-rw-r--r--src/coins.cpp8
-rw-r--r--src/coins.h1
-rw-r--r--src/compat/compat.h (renamed from src/compat.h)46
-rw-r--r--src/consensus/consensus.h2
-rw-r--r--src/consensus/params.h5
-rw-r--r--src/consensus/validation.h1
-rw-r--r--src/core_read.cpp2
-rw-r--r--src/crc32c/CMakeLists.txt7
-rw-r--r--src/crypto/muhash.cpp4
-rw-r--r--src/cuckoocache.h23
-rw-r--r--src/dbwrapper.cpp21
-rw-r--r--src/dbwrapper.h37
-rw-r--r--src/external_signer.cpp4
-rw-r--r--src/fs.cpp2
-rw-r--r--src/fs.h6
-rw-r--r--src/hash.cpp6
-rw-r--r--src/hash.h36
-rw-r--r--src/headerssync.cpp317
-rw-r--r--src/headerssync.h277
-rw-r--r--src/httpserver.cpp8
-rw-r--r--src/i2p.cpp68
-rw-r--r--src/i2p.h21
-rw-r--r--src/index/base.cpp84
-rw-r--r--src/index/base.h37
-rw-r--r--src/index/blockfilterindex.cpp65
-rw-r--r--src/index/blockfilterindex.h20
-rw-r--r--src/index/coinstatsindex.cpp74
-rw-r--r--src/index/coinstatsindex.h24
-rw-r--r--src/index/txindex.cpp17
-rw-r--r--src/index/txindex.h6
-rw-r--r--src/init.cpp359
-rw-r--r--src/init/common.cpp30
-rw-r--r--src/init/common.h1
-rw-r--r--src/interfaces/chain.h38
-rw-r--r--src/interfaces/node.h2
-rw-r--r--src/interfaces/wallet.h50
-rw-r--r--src/kernel/chain.cpp26
-rw-r--r--src/kernel/chain.h19
-rw-r--r--src/kernel/chainstatemanager_opts.h8
-rw-r--r--src/kernel/checks.cpp11
-rw-r--r--src/kernel/checks.h10
-rw-r--r--src/kernel/coinstats.cpp24
-rw-r--r--src/kernel/coinstats.h6
-rw-r--r--src/kernel/mempool_limits.h30
-rw-r--r--src/kernel/mempool_options.h60
-rw-r--r--src/kernel/mempool_persist.cpp189
-rw-r--r--src/kernel/mempool_persist.h28
-rw-r--r--src/kernel/validation_cache_sizes.h20
-rw-r--r--src/key.cpp1
-rw-r--r--src/key.h4
-rw-r--r--src/leveldb/util/env_posix.cc2
-rw-r--r--src/logging.cpp85
-rw-r--r--src/logging.h55
-rw-r--r--src/mapport.cpp2
-rw-r--r--src/minisketch/README.md4
-rw-r--r--src/minisketch/include/minisketch.h3
-rw-r--r--src/net.cpp461
-rw-r--r--src/net.h230
-rw-r--r--src/net_processing.cpp1268
-rw-r--r--src/net_processing.h10
-rw-r--r--src/netaddress.h2
-rw-r--r--src/netbase.cpp8
-rw-r--r--src/netbase.h2
-rw-r--r--src/node/blockstorage.cpp16
-rw-r--r--src/node/blockstorage.h8
-rw-r--r--src/node/chainstate.cpp139
-rw-r--r--src/node/chainstate.h85
-rw-r--r--src/node/connection_types.cpp26
-rw-r--r--src/node/connection_types.h82
-rw-r--r--src/node/eviction.cpp240
-rw-r--r--src/node/eviction.h69
-rw-r--r--src/node/interface_ui.cpp2
-rw-r--r--src/node/interface_ui.h2
-rw-r--r--src/node/interfaces.cpp146
-rw-r--r--src/node/mempool_args.cpp100
-rw-r--r--src/node/mempool_args.h27
-rw-r--r--src/node/mempool_persist_args.cpp23
-rw-r--r--src/node/mempool_persist_args.h25
-rw-r--r--src/node/miner.cpp8
-rw-r--r--src/node/miner.h6
-rw-r--r--src/node/psbt.cpp2
-rw-r--r--src/node/utxo_snapshot.h2
-rw-r--r--src/node/validation_cache_args.cpp34
-rw-r--r--src/node/validation_cache_args.h17
-rw-r--r--src/outputtype.cpp12
-rw-r--r--src/outputtype.h1
-rw-r--r--src/policy/fees.cpp28
-rw-r--r--src/policy/fees.h10
-rw-r--r--src/policy/fees_args.cpp12
-rw-r--r--src/policy/fees_args.h15
-rw-r--r--src/policy/packages.h4
-rw-r--r--src/policy/policy.cpp13
-rw-r--r--src/policy/policy.h19
-rw-r--r--src/policy/rbf.cpp12
-rw-r--r--src/policy/rbf.h30
-rw-r--r--src/policy/settings.cpp5
-rw-r--r--src/policy/settings.h29
-rw-r--r--src/pow.cpp51
-rw-r--r--src/pow.h14
-rw-r--r--src/primitives/block.h8
-rw-r--r--src/primitives/transaction.cpp7
-rw-r--r--src/primitives/transaction.h14
-rw-r--r--src/protocol.cpp7
-rw-r--r--src/protocol.h11
-rw-r--r--src/psbt.cpp75
-rw-r--r--src/psbt.h295
-rw-r--r--src/pubkey.cpp7
-rw-r--r--src/pubkey.h7
-rw-r--r--src/qt/addresstablemodel.cpp14
-rw-r--r--src/qt/bitcoin.cpp27
-rw-r--r--src/qt/bitcoin_locale.qrc7
-rw-r--r--src/qt/bitcoingui.cpp74
-rw-r--r--src/qt/bitcoingui.h6
-rw-r--r--src/qt/bitcoinstrings.cpp87
-rw-r--r--src/qt/clientmodel.cpp18
-rw-r--r--src/qt/clientmodel.h10
-rw-r--r--src/qt/forms/intro.ui2
-rw-r--r--src/qt/guiutil.cpp9
-rw-r--r--src/qt/locale/bitcoin_am.ts26
-rw-r--r--src/qt/locale/bitcoin_ar.ts148
-rw-r--r--src/qt/locale/bitcoin_az.ts1043
-rw-r--r--src/qt/locale/bitcoin_be.ts36
-rw-r--r--src/qt/locale/bitcoin_bg.ts550
-rw-r--r--src/qt/locale/bitcoin_bn.ts60
-rw-r--r--src/qt/locale/bitcoin_bs.ts37
-rw-r--r--src/qt/locale/bitcoin_ca.ts144
-rw-r--r--src/qt/locale/bitcoin_cs.ts632
-rw-r--r--src/qt/locale/bitcoin_cy.ts30
-rw-r--r--src/qt/locale/bitcoin_da.ts860
-rw-r--r--src/qt/locale/bitcoin_de.ts436
-rw-r--r--src/qt/locale/bitcoin_el.ts306
-rw-r--r--src/qt/locale/bitcoin_en.ts701
-rw-r--r--src/qt/locale/bitcoin_en.xlf3644
-rw-r--r--src/qt/locale/bitcoin_eo.ts39
-rw-r--r--src/qt/locale/bitcoin_es.ts2554
-rw-r--r--src/qt/locale/bitcoin_es_CL.ts70
-rw-r--r--src/qt/locale/bitcoin_es_CO.ts78
-rw-r--r--src/qt/locale/bitcoin_es_DO.ts63
-rw-r--r--src/qt/locale/bitcoin_es_MX.ts2478
-rw-r--r--src/qt/locale/bitcoin_es_VE.ts33
-rw-r--r--src/qt/locale/bitcoin_et.ts44
-rw-r--r--src/qt/locale/bitcoin_eu.ts735
-rw-r--r--src/qt/locale/bitcoin_fa.ts233
-rw-r--r--src/qt/locale/bitcoin_fi.ts122
-rw-r--r--src/qt/locale/bitcoin_fil.ts136
-rw-r--r--src/qt/locale/bitcoin_fr.ts388
-rw-r--r--src/qt/locale/bitcoin_ga.ts92
-rw-r--r--src/qt/locale/bitcoin_gd.ts32
-rw-r--r--src/qt/locale/bitcoin_gl.ts32
-rw-r--r--src/qt/locale/bitcoin_gl_ES.ts26
-rw-r--r--src/qt/locale/bitcoin_gu.ts21
-rw-r--r--src/qt/locale/bitcoin_ha.ts185
-rw-r--r--src/qt/locale/bitcoin_he.ts95
-rw-r--r--src/qt/locale/bitcoin_hr.ts1355
-rw-r--r--src/qt/locale/bitcoin_hu.ts250
-rw-r--r--src/qt/locale/bitcoin_id.ts507
-rw-r--r--src/qt/locale/bitcoin_is.ts21
-rw-r--r--src/qt/locale/bitcoin_it.ts309
-rw-r--r--src/qt/locale/bitcoin_ja.ts146
-rw-r--r--src/qt/locale/bitcoin_ka.ts49
-rw-r--r--src/qt/locale/bitcoin_kk.ts35
-rw-r--r--src/qt/locale/bitcoin_kl.ts21
-rw-r--r--src/qt/locale/bitcoin_km.ts51
-rw-r--r--src/qt/locale/bitcoin_ko.ts434
-rw-r--r--src/qt/locale/bitcoin_ku.ts357
-rw-r--r--src/qt/locale/bitcoin_ku_IQ.ts45
-rw-r--r--src/qt/locale/bitcoin_ky.ts21
-rw-r--r--src/qt/locale/bitcoin_la.ts28
-rw-r--r--src/qt/locale/bitcoin_lt.ts124
-rw-r--r--src/qt/locale/bitcoin_lv.ts95
-rw-r--r--src/qt/locale/bitcoin_mk.ts24
-rw-r--r--src/qt/locale/bitcoin_ml.ts35
-rw-r--r--src/qt/locale/bitcoin_mn.ts28
-rw-r--r--src/qt/locale/bitcoin_mr_IN.ts118
-rw-r--r--src/qt/locale/bitcoin_ms.ts18
-rw-r--r--src/qt/locale/bitcoin_my.ts18
-rw-r--r--src/qt/locale/bitcoin_nb.ts235
-rw-r--r--src/qt/locale/bitcoin_ne.ts149
-rw-r--r--src/qt/locale/bitcoin_nl.ts687
-rw-r--r--src/qt/locale/bitcoin_no.ts21
-rw-r--r--src/qt/locale/bitcoin_pa.ts448
-rw-r--r--src/qt/locale/bitcoin_pam.ts24
-rw-r--r--src/qt/locale/bitcoin_pl.ts886
-rw-r--r--src/qt/locale/bitcoin_pt.ts251
-rw-r--r--src/qt/locale/bitcoin_pt_BR.ts557
-rw-r--r--src/qt/locale/bitcoin_ro.ts82
-rw-r--r--src/qt/locale/bitcoin_ru.ts1349
-rw-r--r--src/qt/locale/bitcoin_sc.ts18
-rw-r--r--src/qt/locale/bitcoin_si.ts153
-rw-r--r--src/qt/locale/bitcoin_sk.ts330
-rw-r--r--src/qt/locale/bitcoin_sl.ts392
-rw-r--r--src/qt/locale/bitcoin_sn.ts21
-rw-r--r--src/qt/locale/bitcoin_sq.ts27
-rw-r--r--src/qt/locale/bitcoin_sr.ts743
-rw-r--r--src/qt/locale/bitcoin_sr@latin.ts26
-rw-r--r--src/qt/locale/bitcoin_sv.ts286
-rw-r--r--src/qt/locale/bitcoin_sw.ts21
-rw-r--r--src/qt/locale/bitcoin_szl.ts24
-rw-r--r--src/qt/locale/bitcoin_ta.ts137
-rw-r--r--src/qt/locale/bitcoin_te.ts21
-rw-r--r--src/qt/locale/bitcoin_th.ts2122
-rw-r--r--src/qt/locale/bitcoin_tk.ts1577
-rw-r--r--src/qt/locale/bitcoin_tl.ts1527
-rw-r--r--src/qt/locale/bitcoin_tr.ts240
-rw-r--r--src/qt/locale/bitcoin_ug.ts21
-rw-r--r--src/qt/locale/bitcoin_uk.ts561
-rw-r--r--src/qt/locale/bitcoin_ur.ts1693
-rw-r--r--src/qt/locale/bitcoin_uz.ts225
-rw-r--r--src/qt/locale/bitcoin_uz@Cyrl.ts73
-rw-r--r--src/qt/locale/bitcoin_uz@Latn.ts106
-rw-r--r--src/qt/locale/bitcoin_vi.ts2272
-rw-r--r--src/qt/locale/bitcoin_yo.ts18
-rw-r--r--src/qt/locale/bitcoin_zh-Hans.ts4561
-rw-r--r--src/qt/locale/bitcoin_zh.ts456
-rw-r--r--src/qt/locale/bitcoin_zh_CN.ts585
-rw-r--r--src/qt/locale/bitcoin_zh_HK.ts18
-rw-r--r--src/qt/locale/bitcoin_zh_TW.ts400
-rw-r--r--src/qt/locale/bitcoin_zu.ts48
-rw-r--r--src/qt/main.cpp2
-rw-r--r--src/qt/modaloverlay.cpp12
-rw-r--r--src/qt/modaloverlay.h3
-rw-r--r--src/qt/optionsdialog.cpp26
-rw-r--r--src/qt/optionsdialog.h3
-rw-r--r--src/qt/overviewpage.cpp23
-rw-r--r--src/qt/overviewpage.h1
-rw-r--r--src/qt/rpcconsole.cpp12
-rw-r--r--src/qt/rpcconsole.h4
-rw-r--r--src/qt/sendcoinsdialog.cpp14
-rw-r--r--src/qt/sendcoinsdialog.h6
-rw-r--r--src/qt/splashscreen.cpp2
-rw-r--r--src/qt/test/test_main.cpp2
-rw-r--r--src/qt/test/wallettests.cpp34
-rw-r--r--src/qt/walletcontroller.cpp67
-rw-r--r--src/qt/walletcontroller.h20
-rw-r--r--src/qt/walletframe.cpp10
-rw-r--r--src/qt/walletmodel.cpp31
-rw-r--r--src/qt/walletmodel.h8
-rw-r--r--src/random.cpp2
-rw-r--r--src/random.h17
-rw-r--r--src/randomenv.cpp2
-rw-r--r--src/rest.cpp55
-rw-r--r--src/rpc/blockchain.cpp105
-rw-r--r--src/rpc/blockchain.h6
-rw-r--r--src/rpc/client.cpp4
-rw-r--r--src/rpc/fees.cpp7
-rw-r--r--src/rpc/mempool.cpp182
-rw-r--r--src/rpc/mining.cpp30
-rw-r--r--src/rpc/net.cpp52
-rw-r--r--src/rpc/node.cpp6
-rw-r--r--src/rpc/output_script.cpp7
-rw-r--r--src/rpc/rawtransaction.cpp445
-rw-r--r--src/rpc/rawtransaction_util.cpp11
-rw-r--r--src/rpc/rawtransaction_util.h3
-rw-r--r--src/rpc/request.cpp6
-rw-r--r--src/rpc/server.cpp10
-rw-r--r--src/rpc/txoutproof.cpp2
-rw-r--r--src/rpc/util.cpp5
-rw-r--r--src/script/descriptor.cpp326
-rw-r--r--src/script/interpreter.cpp32
-rw-r--r--src/script/interpreter.h10
-rw-r--r--src/script/miniscript.h310
-rw-r--r--src/script/script.h2
-rw-r--r--src/script/sigcache.cpp18
-rw-r--r--src/script/sigcache.h11
-rw-r--r--src/script/sign.cpp56
-rw-r--r--src/script/sign.h10
-rw-r--r--src/script/signingprovider.cpp37
-rw-r--r--src/script/signingprovider.h10
-rw-r--r--src/script/standard.cpp28
-rw-r--r--src/script/standard.h15
-rw-r--r--src/serialize.h23
-rw-r--r--src/streams.h69
-rw-r--r--src/sync.h2
-rw-r--r--src/test/addrman_tests.cpp26
-rw-r--r--src/test/base58_tests.cpp4
-rw-r--r--src/test/bip32_tests.cpp18
-rw-r--r--src/test/blockfilter_index_tests.cpp19
-rw-r--r--src/test/blockfilter_tests.cpp2
-rw-r--r--src/test/coinstatsindex_tests.cpp29
-rw-r--r--src/test/denialofservice_tests.cpp53
-rw-r--r--src/test/descriptor_tests.cpp153
-rw-r--r--src/test/flatfile_tests.cpp12
-rw-r--r--src/test/fuzz/addrman.cpp18
-rw-r--r--src/test/fuzz/autofile.cpp4
-rw-r--r--src/test/fuzz/bitdeque.cpp541
-rw-r--r--src/test/fuzz/chain.cpp3
-rw-r--r--src/test/fuzz/integer.cpp3
-rw-r--r--src/test/fuzz/key.cpp6
-rw-r--r--src/test/fuzz/load_external_block_file.cpp11
-rw-r--r--src/test/fuzz/mempool_utils.h19
-rw-r--r--src/test/fuzz/net.cpp1
-rw-r--r--src/test/fuzz/node_eviction.cpp2
-rw-r--r--src/test/fuzz/parse_univalue.cpp2
-rw-r--r--src/test/fuzz/policy_estimator.cpp10
-rw-r--r--src/test/fuzz/policy_estimator_io.cpp10
-rw-r--r--src/test/fuzz/pow.cpp37
-rw-r--r--src/test/fuzz/process_message.cpp3
-rw-r--r--src/test/fuzz/process_messages.cpp3
-rw-r--r--src/test/fuzz/rbf.cpp21
-rw-r--r--src/test/fuzz/rpc.cpp1
-rw-r--r--src/test/fuzz/script.cpp3
-rw-r--r--src/test/fuzz/script_sigcache.cpp11
-rw-r--r--src/test/fuzz/transaction.cpp5
-rw-r--r--src/test/fuzz/tx_pool.cpp47
-rw-r--r--src/test/fuzz/txorphan.cpp146
-rw-r--r--src/test/fuzz/util.cpp126
-rw-r--r--src/test/fuzz/util.h34
-rw-r--r--src/test/fuzz/utxo_snapshot.cpp6
-rw-r--r--src/test/fuzz/validation_load_mempool.cpp19
-rw-r--r--src/test/headers_sync_chainwork_tests.cpp146
-rw-r--r--src/test/i2p_tests.cpp6
-rw-r--r--src/test/interfaces_tests.cpp6
-rw-r--r--src/test/key_io_tests.cpp6
-rw-r--r--src/test/logging_tests.cpp125
-rw-r--r--src/test/mempool_tests.cpp8
-rw-r--r--src/test/miner_tests.cpp22
-rw-r--r--src/test/miniscript_tests.cpp20
-rw-r--r--src/test/multisig_tests.cpp22
-rw-r--r--src/test/net_tests.cpp27
-rw-r--r--src/test/netbase_tests.cpp18
-rw-r--r--src/test/pow_tests.cpp27
-rw-r--r--src/test/random_tests.cpp10
-rw-r--r--src/test/rbf_tests.cpp230
-rw-r--r--src/test/result_tests.cpp96
-rw-r--r--src/test/rpc_tests.cpp4
-rw-r--r--src/test/script_p2sh_tests.cpp14
-rw-r--r--src/test/script_tests.cpp28
-rw-r--r--src/test/sighash_tests.cpp2
-rw-r--r--src/test/skiplist_tests.cpp8
-rw-r--r--src/test/sock_tests.cpp20
-rw-r--r--src/test/system_tests.cpp5
-rw-r--r--src/test/transaction_tests.cpp30
-rw-r--r--src/test/txindex_tests.cpp5
-rw-r--r--src/test/txvalidationcache_tests.cpp5
-rw-r--r--src/test/util/chainstate.h13
-rw-r--r--src/test/util/mining.cpp2
-rw-r--r--src/test/util/net.cpp60
-rw-r--r--src/test/util/net.h27
-rw-r--r--src/test/util/setup_common.cpp81
-rw-r--r--src/test/util/setup_common.h7
-rw-r--r--src/test/util/validation.h2
-rw-r--r--src/test/util/wallet.cpp7
-rw-r--r--src/test/util_tests.cpp35
-rw-r--r--src/test/validation_block_tests.cpp17
-rw-r--r--src/test/validation_chainstate_tests.cpp21
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp48
-rw-r--r--src/test/validation_flush_tests.cpp13
-rw-r--r--src/threadinterrupt.cpp12
-rw-r--r--src/threadinterrupt.h6
-rw-r--r--src/timedata.cpp4
-rw-r--r--src/timedata.h9
-rw-r--r--src/torcontrol.cpp2
-rw-r--r--src/txdb.cpp8
-rw-r--r--src/txdb.h1
-rw-r--r--src/txmempool.cpp111
-rw-r--r--src/txmempool.h83
-rw-r--r--src/txorphanage.cpp4
-rw-r--r--src/txorphanage.h2
-rw-r--r--src/uint256.h11
-rw-r--r--src/univalue/include/univalue.h107
-rw-r--r--src/univalue/lib/univalue.cpp84
-rw-r--r--src/univalue/lib/univalue_get.cpp19
-rw-r--r--src/univalue/sources.mk9
-rw-r--r--src/univalue/test/.gitignore1
-rw-r--r--src/univalue/test/no_nul.cpp8
-rw-r--r--src/univalue/test/object.cpp119
-rw-r--r--src/univalue/test/unitester.cpp8
-rw-r--r--src/util/asmap.cpp7
-rw-r--r--src/util/bip32.cpp5
-rw-r--r--src/util/bip32.h1
-rw-r--r--src/util/bitdeque.h469
-rw-r--r--src/util/bytevectorhash.cpp2
-rw-r--r--src/util/bytevectorhash.h3
-rw-r--r--src/util/designator.h21
-rw-r--r--src/util/error.cpp6
-rw-r--r--src/util/error.h1
-rw-r--r--src/util/hasher.cpp4
-rw-r--r--src/util/hasher.h6
-rw-r--r--src/util/message.cpp19
-rw-r--r--src/util/message.h3
-rw-r--r--src/util/moneystr.cpp1
-rw-r--r--src/util/readwritefile.cpp3
-rw-r--r--src/util/result.h84
-rw-r--r--src/util/serfloat.h2
-rw-r--r--src/util/sock.cpp62
-rw-r--r--src/util/sock.h42
-rw-r--r--src/util/spanparsing.cpp3
-rw-r--r--src/util/strencodings.cpp10
-rw-r--r--src/util/strencodings.h5
-rw-r--r--src/util/string.cpp8
-rw-r--r--src/util/string.h39
-rw-r--r--src/util/syserror.cpp1
-rw-r--r--src/util/system.cpp87
-rw-r--r--src/util/system.h14
-rw-r--r--src/util/thread.cpp7
-rw-r--r--src/util/thread.h3
-rw-r--r--src/util/time.cpp13
-rw-r--r--src/util/time.h18
-rw-r--r--src/util/translation.h2
-rw-r--r--src/util/url.cpp3
-rw-r--r--src/util/vector.h1
-rw-r--r--src/validation.cpp525
-rw-r--r--src/validation.h171
-rw-r--r--src/wallet/bdb.cpp17
-rw-r--r--src/wallet/coinselection.cpp62
-rw-r--r--src/wallet/coinselection.h48
-rw-r--r--src/wallet/dump.cpp4
-rw-r--r--src/wallet/external_signer_scriptpubkeyman.cpp3
-rw-r--r--src/wallet/feebumper.cpp113
-rw-r--r--src/wallet/feebumper.h66
-rw-r--r--src/wallet/fees.cpp2
-rw-r--r--src/wallet/interfaces.cpp87
-rw-r--r--src/wallet/load.cpp2
-rw-r--r--src/wallet/receive.cpp82
-rw-r--r--src/wallet/receive.h9
-rw-r--r--src/wallet/rpc/addresses.cpp81
-rw-r--r--src/wallet/rpc/backup.cpp131
-rw-r--r--src/wallet/rpc/coins.cpp28
-rw-r--r--src/wallet/rpc/encrypt.cpp14
-rw-r--r--src/wallet/rpc/signmessage.cpp2
-rw-r--r--src/wallet/rpc/spend.cpp101
-rw-r--r--src/wallet/rpc/transactions.cpp126
-rw-r--r--src/wallet/rpc/util.cpp18
-rw-r--r--src/wallet/rpc/util.h4
-rw-r--r--src/wallet/rpc/wallet.cpp182
-rw-r--r--src/wallet/scriptpubkeyman.cpp449
-rw-r--r--src/wallet/scriptpubkeyman.h29
-rw-r--r--src/wallet/spend.cpp437
-rw-r--r--src/wallet/spend.h91
-rw-r--r--src/wallet/test/availablecoins_tests.cpp107
-rw-r--r--src/wallet/test/coinselector_tests.cpp396
-rw-r--r--src/wallet/test/feebumper_tests.cpp54
-rw-r--r--src/wallet/test/fuzz/coinselection.cpp8
-rw-r--r--src/wallet/test/fuzz/notifications.cpp28
-rw-r--r--src/wallet/test/ismine_tests.cpp37
-rw-r--r--src/wallet/test/spend_tests.cpp62
-rw-r--r--src/wallet/test/util.cpp2
-rw-r--r--src/wallet/test/wallet_tests.cpp192
-rw-r--r--src/wallet/test/walletload_tests.cpp54
-rw-r--r--src/wallet/transaction.h7
-rw-r--r--src/wallet/wallet.cpp1002
-rw-r--r--src/wallet/wallet.h114
-rw-r--r--src/wallet/walletdb.cpp108
-rw-r--r--src/wallet/walletdb.h10
-rw-r--r--src/wallet/wallettool.cpp2
-rw-r--r--src/wallet/walletutil.h14
-rw-r--r--src/zmq/zmqnotificationinterface.cpp2
-rw-r--r--src/zmq/zmqpublishnotifier.cpp1
-rw-r--r--test/README.md6
-rw-r--r--test/functional/README.md4
-rw-r--r--test/functional/data/rpc_decodescript.json2
-rw-r--r--test/functional/data/rpc_psbt.json31
-rwxr-xr-xtest/functional/example_test.py11
-rwxr-xr-xtest/functional/feature_addrman.py2
-rwxr-xr-xtest/functional/feature_block.py2
-rwxr-xr-xtest/functional/feature_config_args.py3
-rwxr-xr-xtest/functional/feature_dbcrash.py16
-rwxr-xr-xtest/functional/feature_fee_estimation.py3
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py2
-rwxr-xr-xtest/functional/feature_minchainwork.py2
-rwxr-xr-xtest/functional/feature_nulldummy.py65
-rwxr-xr-xtest/functional/feature_proxy.py31
-rwxr-xr-xtest/functional/feature_rbf.py437
-rwxr-xr-xtest/functional/feature_segwit.py5
-rwxr-xr-xtest/functional/feature_signet.py8
-rwxr-xr-xtest/functional/feature_taproot.py16
-rwxr-xr-xtest/functional/interface_usdt_net.py2
-rwxr-xr-xtest/functional/interface_usdt_utxocache.py43
-rwxr-xr-xtest/functional/interface_usdt_validation.py13
-rwxr-xr-xtest/functional/mempool_accept.py8
-rwxr-xr-xtest/functional/mempool_datacarrier.py71
-rwxr-xr-xtest/functional/mempool_expiry.py8
-rwxr-xr-xtest/functional/mempool_limit.py2
-rwxr-xr-xtest/functional/mempool_package_limits.py316
-rwxr-xr-xtest/functional/mempool_package_onemore.py17
-rwxr-xr-xtest/functional/mempool_packages.py45
-rwxr-xr-xtest/functional/mempool_persist.py26
-rwxr-xr-xtest/functional/mempool_reorg.py6
-rwxr-xr-xtest/functional/mempool_updatefromblock.py19
-rwxr-xr-xtest/functional/mining_prioritisetransaction.py6
-rwxr-xr-xtest/functional/mocks/invalid_signer.py2
-rwxr-xr-xtest/functional/mocks/multi_signers.py30
-rwxr-xr-xtest/functional/mocks/signer.py2
-rwxr-xr-xtest/functional/p2p_compactblocks.py24
-rwxr-xr-xtest/functional/p2p_dos_header_tree.py3
-rwxr-xr-xtest/functional/p2p_headers_sync_with_minchainwork.py164
-rwxr-xr-xtest/functional/p2p_i2p_sessions.py36
-rwxr-xr-xtest/functional/p2p_initial_headers_sync.py105
-rwxr-xr-xtest/functional/p2p_invalid_tx.py68
-rwxr-xr-xtest/functional/p2p_leak.py5
-rwxr-xr-xtest/functional/p2p_permissions.py4
-rwxr-xr-xtest/functional/p2p_segwit.py14
-rwxr-xr-xtest/functional/p2p_timeouts.py5
-rwxr-xr-xtest/functional/p2p_tx_privacy.py78
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py14
-rwxr-xr-xtest/functional/rpc_blockchain.py27
-rwxr-xr-xtest/functional/rpc_deriveaddresses.py7
-rwxr-xr-xtest/functional/rpc_estimatefee.py8
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py192
-rwxr-xr-xtest/functional/rpc_getblockfrompeer.py9
-rwxr-xr-xtest/functional/rpc_getdescriptorinfo.py2
-rwxr-xr-xtest/functional/rpc_help.py2
-rwxr-xr-xtest/functional/rpc_invalidateblock.py5
-rwxr-xr-xtest/functional/rpc_mempool_info.py2
-rwxr-xr-xtest/functional/rpc_packages.py137
-rwxr-xr-xtest/functional/rpc_psbt.py138
-rwxr-xr-xtest/functional/rpc_rawtransaction.py24
-rwxr-xr-xtest/functional/rpc_signer.py5
-rwxr-xr-xtest/functional/rpc_signmessagewithprivkey.py22
-rwxr-xr-xtest/functional/rpc_signrawtransactionwithkey.py140
-rw-r--r--test/functional/test_framework/blocktools.py24
-rw-r--r--test/functional/test_framework/key.py4
-rwxr-xr-xtest/functional/test_framework/messages.py23
-rw-r--r--test/functional/test_framework/psbt.py140
-rwxr-xr-xtest/functional/test_framework/test_framework.py27
-rwxr-xr-xtest/functional/test_framework/test_node.py2
-rw-r--r--test/functional/test_framework/util.py36
-rw-r--r--test/functional/test_framework/wallet.py144
-rwxr-xr-xtest/functional/test_runner.py31
-rwxr-xr-xtest/functional/tool_wallet.py10
-rwxr-xr-xtest/functional/wallet_abandonconflict.py3
-rwxr-xr-xtest/functional/wallet_address_types.py28
-rwxr-xr-xtest/functional/wallet_avoid_mixing_output_types.py177
-rwxr-xr-xtest/functional/wallet_balance.py24
-rwxr-xr-xtest/functional/wallet_basic.py48
-rwxr-xr-xtest/functional/wallet_bumpfee.py34
-rwxr-xr-xtest/functional/wallet_coinbase_category.py1
-rwxr-xr-xtest/functional/wallet_encryption.py18
-rwxr-xr-xtest/functional/wallet_groups.py7
-rwxr-xr-xtest/functional/wallet_hd.py8
-rwxr-xr-xtest/functional/wallet_import_rescan.py57
-rwxr-xr-xtest/functional/wallet_importdescriptors.py9
-rwxr-xr-xtest/functional/wallet_listreceivedby.py7
-rwxr-xr-xtest/functional/wallet_listsinceblock.py84
-rwxr-xr-xtest/functional/wallet_listtransactions.py18
-rwxr-xr-xtest/functional/wallet_migration.py417
-rwxr-xr-xtest/functional/wallet_miniscript.py93
-rwxr-xr-xtest/functional/wallet_multiwallet.py2
-rwxr-xr-xtest/functional/wallet_resendwallettransactions.py74
-rwxr-xr-xtest/functional/wallet_sendall.py67
-rwxr-xr-xtest/functional/wallet_signer.py15
-rwxr-xr-xtest/functional/wallet_signrawtransactionwithwallet.py (renamed from test/functional/rpc_signrawtransaction.py)100
-rwxr-xr-xtest/functional/wallet_simulaterawtx.py129
-rwxr-xr-xtest/functional/wallet_taproot.py163
-rwxr-xr-xtest/functional/wallet_transactiontime_rescan.py7
-rwxr-xr-xtest/get_previous_releases.py113
-rwxr-xr-xtest/lint/lint-circular-dependencies.py4
-rwxr-xr-xtest/lint/lint-git-commit-check.py2
-rwxr-xr-xtest/lint/lint-includes.py3
-rwxr-xr-xtest/lint/lint-whitespace.py2
-rw-r--r--test/sanitizer_suppressions/tsan2
-rw-r--r--test/sanitizer_suppressions/ubsan4
687 files changed, 55671 insertions, 18638 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index a4196dc927..fdecfc1eb6 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -24,14 +24,11 @@ filter_template: &FILTER_TEMPLATE
base_template: &BASE_TEMPLATE
<< : *FILTER_TEMPLATE
merge_base_script:
- # Unconditionally install git (used in fingerprint_script) and set the
- # default git author name (used in verify-commits.py)
+ # Unconditionally install git (used in fingerprint_script).
- bash -c "$PACKAGE_MANAGER_INSTALL git"
- - git config --global user.email "ci@ci.ci"
- - git config --global user.name "ci"
- if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
- - git fetch $CIRRUS_REPO_CLONE_URL $CIRRUS_BASE_BRANCH
- - git merge FETCH_HEAD # Merge base to detect silent merge conflicts
+ - git fetch $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge"
+ - git checkout FETCH_HEAD # Use merged changes to detect silent merge conflicts
main_template: &MAIN_TEMPLATE
timeout_in: 120m # https://cirrus-ci.org/faq/#instance-timed-out
@@ -94,37 +91,30 @@ task:
FILE_ENV: "./ci/test/00_setup_env_native_tidy.sh"
task:
- name: "Win64 native [msvc]"
+ name: "Win64 native [vs2022]"
<< : *FILTER_TEMPLATE
windows_container:
- cpu: 4
- memory: 8G
- image: cirrusci/windowsservercore:visualstudio2019
+ cpu: 6
+ memory: 12G
+ image: cirrusci/windowsservercore:visualstudio2022
timeout_in: 120m
env:
- PATH: 'C:\jom;C:\Python39;C:\Python39\Scripts;C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin;%PATH%'
+ PATH: 'C:\jom;C:\Python39;C:\Python39\Scripts;C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin;%PATH%'
PYTHONUTF8: 1
- CI_VCPKG_TAG: '2022.04.12'
+ CI_VCPKG_TAG: '2022.06.16.1'
VCPKG_DOWNLOADS: 'C:\Users\ContainerAdministrator\AppData\Local\vcpkg\downloads'
VCPKG_DEFAULT_BINARY_CACHE: 'C:\Users\ContainerAdministrator\AppData\Local\vcpkg\archives'
CCACHE_DIR: 'C:\Users\ContainerAdministrator\AppData\Local\ccache'
WRAPPED_CL: 'C:\Users\ContainerAdministrator\AppData\Local\Temp\cirrus-ci-build\ci\test\wrapped-cl.bat'
- QT_DOWNLOAD_URL: 'https://download.qt.io/official_releases/qt/5.15/5.15.3/single/qt-everywhere-opensource-src-5.15.3.zip'
- QT_LOCAL_PATH: 'C:\qt-everywhere-opensource-src-5.15.3.zip'
- QT_SOURCE_DIR: 'C:\qt-everywhere-src-5.15.3'
+ QT_DOWNLOAD_URL: 'https://download.qt.io/official_releases/qt/5.15/5.15.5/single/qt-everywhere-opensource-src-5.15.5.zip'
+ QT_LOCAL_PATH: 'C:\qt-everywhere-opensource-src-5.15.5.zip'
+ QT_SOURCE_DIR: 'C:\qt-everywhere-src-5.15.5'
QTBASEDIR: 'C:\Qt_static'
- x64_NATIVE_TOOLS: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"'
+ x64_NATIVE_TOOLS: '"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat"'
QT_CONFIGURE_COMMAND: '..\configure -release -silent -opensource -confirm-license -opengl desktop -static -static-runtime -mp -qt-zlib -qt-pcre -qt-libpng -nomake examples -nomake tests -nomake tools -no-angle -no-dbus -no-gif -no-gtk -no-ico -no-icu -no-libjpeg -no-libudev -no-sql-sqlite -no-sql-odbc -no-sqlite -no-vulkan -skip qt3d -skip qtactiveqt -skip qtandroidextras -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdeclarative -skip doc -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtlottie -skip qtmacextras -skip qtmultimedia -skip qtnetworkauth -skip qtpurchasing -skip qtquick3d -skip qtquickcontrols -skip qtquickcontrols2 -skip qtquicktimeline -skip qtremoteobjects -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtsvg -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebglplugin -skip qtwebsockets -skip qtwebview -skip qtx11extras -skip qtxmlpatterns -no-openssl -no-feature-bearermanagement -no-feature-printdialog -no-feature-printer -no-feature-printpreviewdialog -no-feature-printpreviewwidget -no-feature-sql -no-feature-sqlmodel -no-feature-textbrowser -no-feature-textmarkdownwriter -no-feature-textodfwriter -no-feature-xml'
IgnoreWarnIntDirInTempDetected: 'true'
merge_script:
- - git config --global user.email "ci@ci.ci"
- - git config --global user.name "ci"
- # Windows filesystem loses the executable bit, and all of the executable
- # files are considered "modified" now. It will break the following `git merge`
- # command. The next two commands make git ignore this issue.
- - git config core.filemode false
- - git reset --hard
- - PowerShell -NoLogo -Command if ($env:CIRRUS_PR -ne $null) { git fetch $env:CIRRUS_REPO_CLONE_URL $env:CIRRUS_BASE_BRANCH; git merge FETCH_HEAD; }
+ - PowerShell -NoLogo -Command if ($env:CIRRUS_PR -ne $null) { git fetch $env:CIRRUS_REPO_CLONE_URL pull/$env:CIRRUS_PR/merge; git checkout FETCH_HEAD; }
msvc_qt_built_cache:
folder: "%QTBASEDIR%"
reupload_on_changes: false
@@ -162,7 +152,7 @@ task:
ccache_cache:
folder: '%CCACHE_DIR%'
install_tools_script:
- - choco install --yes --no-progress ccache
+ - choco install --yes --no-progress ccache --version=4.6.1
- choco install --yes --no-progress python3 --version=3.9.6
- pip install zmq
- ccache --version
@@ -179,7 +169,7 @@ task:
build_script:
- '%x64_NATIVE_TOOLS%'
- cd %CIRRUS_WORKING_DIR%
- - ccache --zero-stats
+ - ccache --zero-stats --max-size=%CCACHE_SIZE%
- python build_msvc\msvc-autogen.py
- msbuild build_msvc\bitcoin.sln -property:CLToolExe=%WRAPPED_CL% -property:Configuration=Release -maxCpuCount -verbosity:minimal -noLogo
- ccache --show-stats
@@ -259,12 +249,20 @@ task:
MAKEJOBS: "-j4" # Avoid excessive memory use due to MSan
task:
- name: '[ASan + LSan + UBSan + integer, no depends] [jammy]'
+ name: '[ASan + LSan + UBSan + integer, no depends, USDT] [jammy]'
<< : *GLOBAL_TASK_TEMPLATE
- container:
- image: ubuntu:jammy
+ # We can't use a 'container' for the USDT interface tests as the CirrusCI
+ # containers don't have privileges to hook into bitcoind. CirrusCI uses
+ # Google Compute Engine instances: https://cirrus-ci.org/guide/custom-vms/
+ # Images can be found here: https://cloud.google.com/compute/docs/images/os-details
+ compute_engine_instance:
+ image_project: ubuntu-os-cloud
+ image: family/ubuntu-2204-lts # when upgrading, check if we can drop "ADD_UNTRUSTED_BPFCC_PPA"
+ cpu: 4
+ memory: 12G
env:
<< : *CIRRUS_EPHEMERAL_WORKER_TEMPLATE_ENV
+ HOME: /root/ # Only needed for compute_engine_instance
FILE_ENV: "./ci/test/00_setup_env_native_asan.sh"
MAKEJOBS: "-j4" # Avoid excessive memory use
diff --git a/.tx/config b/.tx/config
index c4fe7cc324..20eff98d28 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,7 +1,7 @@
[main]
host = https://www.transifex.com
-[bitcoin.qt-translation-023x]
+[o:bitcoin:p:bitcoin:r:qt-translation-024x]
file_filter = src/qt/locale/bitcoin_<lang>.xlf
source_file = src/qt/locale/bitcoin_en.xlf
source_lang = en
diff --git a/Makefile.am b/Makefile.am
index 011faa62c7..8b61763ae4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,6 +23,7 @@ endif
BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT)
BITCOIN_QT_BIN=$(top_builddir)/src/qt/$(BITCOIN_GUI_NAME)$(EXEEXT)
+BITCOIN_TEST_BIN=$(top_builddir)/src/test/$(BITCOIN_TEST_NAME)$(EXEEXT)
BITCOIN_CLI_BIN=$(top_builddir)/src/$(BITCOIN_CLI_NAME)$(EXEEXT)
BITCOIN_TX_BIN=$(top_builddir)/src/$(BITCOIN_TX_NAME)$(EXEEXT)
BITCOIN_UTIL_BIN=$(top_builddir)/src/$(BITCOIN_UTIL_NAME)$(EXEEXT)
@@ -78,6 +79,7 @@ $(BITCOIN_WIN_INSTALLER): all-recursive
$(MKDIR_P) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_QT_BIN) $(top_builddir)/release
+ STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_TEST_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_CLI_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_TX_BIN) $(top_builddir)/release
STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_WALLET_BIN) $(top_builddir)/release
diff --git a/REVIEWERS b/REVIEWERS
index dd962947ff..cb1bafa496 100644
--- a/REVIEWERS
+++ b/REVIEWERS
@@ -15,126 +15,3 @@
# review a pull request. Peer review is always welcome and is a critical
# component of the progress of the codebase. Information on peer review
# guidelines can be found in the CONTRIBUTING.md doc.
-
-
-# Maintainers
-# @achow101
-# @fanquake
-# @hebasto
-# @laanwj
-# @marcofalke
-# @sipa
-
-# Docs
-/doc/*[a-zA-Z-].md @harding
-/doc/Doxyfile.in @fanquake
-/doc/REST-interface.md @jonasschnelli
-/doc/benchmarking.md @ariard
-/doc/bitcoin-conf.md @hebasto
-/doc/build-freebsd.md @fanquake
-/doc/build-netbsd.md @fanquake
-/doc/build-openbsd.md @laanwj
-/doc/build-osx.md @fanquake
-/doc/build-unix.md @laanwj
-/doc/build-windows.md @sipsorcery
-/doc/dependencies.md @fanquake
-/doc/developer-notes.md @laanwj
-/doc/files.md @hebasto
-/doc/reduce-memory.md @fanquake
-/doc/reduce-traffic.md @jonasschnelli
-/doc/release-process.md @laanwj
-/doc/translation_strings_policy.md @laanwj
-
-# Build aux
-/build-aux/m4/bitcoin_qt.m4 @hebasto
-
-# MSVC build system
-/build_msvc/ @sipsorcery
-
-# Settings
-/src/util/settings.* @ryanofsky
-
-# Fuzzing
-
-# Tests
-/src/test/net_peer_eviction_tests.cpp @jonatack
-/test/functional/mempool_updatefromblock.py @hebasto
-/test/functional/feature_asmap.py @jonatack
-/test/functional/interface_bitcoin_cli.py @jonatack
-
-# Backwards compatibility tests
-*_compatibility.py @sjors
-/test/functional/wallet_upgradewallet.py @sjors @achow101
-/test/get_previous_releases.py @sjors
-
-# Translations
-/src/util/translation.h @hebasto
-
-# Dev Tools
-/contrib/devtools/security-check.py @fanquake
-/contrib/devtools/test-security-check.py @fanquake
-/contrib/devtools/symbol-check.py @fanquake
-
-# Guix
-/contrib/guix/ @dongcarl
-
-# Compatibility
-/src/compat/glibc_* @fanquake
-
-# GUI
-/src/qt/forms/ @hebasto
-
-# Wallet
-/src/wallet/ @achow101
-
-# CLI
-/src/bitcoin-cli.cpp @jonatack
-
-# Coinstats
-/src/node/coinstats.* @fjahr
-
-# Index
-/src/index/ @fjahr
-
-# Descriptors
-*descriptor* @achow101 @sipa
-
-# External signer
-*external_signer* @sjors
-/doc/external-signer.md @sjors
-*signer.py @sjors
-
-# Interfaces
-/src/interfaces/ @ryanofsky
-
-# DB
-/src/txdb.* @jamesob
-/src/dbwrapper.* @jamesob
-
-# Linter
-/test/lint/lint-shell.py @hebasto
-
-# Bech32
-/src/bech32.* @sipa
-/src/bench/bech32.* @sipa
-
-# PSBT
-/src/psbt* @achow101
-/src/node/psbt* @achow101
-/doc/psbt.md @achow101
-
-# P2P
-/src/net_processing.* @sipa
-/src/protocol.* @sipa
-
-# Consensus
-/src/coins.* @sipa @jamesob
-/src/script/script.* @sipa
-/src/script/interpreter.* @sipa
-/src/validation.* @sipa
-/src/consensus/ @sipa
-
-# Tracing
-/doc/tracing.md @jb55 @0xB10C
-/src/util/trace.h @jb55 @0xB10C
-/contrib/tracing/ @jb55 @0xB10C
diff --git a/SECURITY.md b/SECURITY.md
index 25b6175c95..c0660e7042 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -13,8 +13,8 @@ The following keys may be used to communicate sensitive information to developer
| Name | Fingerprint |
|------|-------------|
-| Wladimir van der Laan | 71A3 B167 3540 5025 D447 E8F2 7481 0B01 2346 C9A6 |
| Pieter Wuille | 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 |
| Michael Ford | E777 299F C265 DD04 7930 70EB 944D 35F9 AC3D B76A |
+| Andrew Chow | 1528 1230 0785 C964 44D3 334D 1756 5732 E08E 5E41 |
You can import a key by running the following command with that individual’s fingerprint: `gpg --keyserver hkps://keys.openpgp.org --recv-keys "<fingerprint>"` Ensure that you put quotes around fingerprints containing spaces.
diff --git a/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4
index 7aac53c815..6c944b160f 100644
--- a/build-aux/m4/ax_boost_base.m4
+++ b/build-aux/m4/ax_boost_base.m4
@@ -11,9 +11,9 @@
# Test for the Boost C++ libraries of a particular version (or newer)
#
# If no path to the installed boost library is given the macro searchs
-# under /usr, /usr/local, /opt, /opt/local and /opt/homebrew and evaluates the
-# $BOOST_ROOT environment variable. Further documentation is available at
-# <http://randspringer.de/boost/index.html>.
+# under /usr, /usr/local, /opt, /opt/local and /opt/homebrew and evaluates
+# the $BOOST_ROOT environment variable. Further documentation is available
+# at <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
@@ -33,7 +33,7 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 48
+#serial 51
# example boost program (need to pass version)
m4_define([_AX_BOOST_BASE_PROGRAM],
@@ -114,7 +114,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
AS_CASE([${host_cpu}],
[x86_64],[libsubdirs="lib64 libx32 lib lib64"],
[mips*64*],[libsubdirs="lib64 lib32 lib lib64"],
- [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs="lib64 lib lib64"],
+ [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64|e2k],[libsubdirs="lib64 lib lib64"],
[libsubdirs="lib"]
)
@@ -128,7 +128,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
)
dnl first we check the system location for boost libraries
- dnl this location ist chosen if boost libraries are installed with the --layout=system option
+ dnl this location is chosen if boost libraries are installed with the --layout=system option
dnl or if you install boost with RPM
AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[
AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"])
@@ -151,7 +151,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
else
search_libsubdirs="$multiarch_libsubdir $libsubdirs"
fi
- for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local /opt/homebrew/; do
+ for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local /opt/homebrew ; do
if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then
for libsubdir in $search_libsubdirs ; do
if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
diff --git a/build-aux/m4/l_atomic.m4 b/build-aux/m4/l_atomic.m4
index 40639dfe61..602b57fe43 100644
--- a/build-aux/m4/l_atomic.m4
+++ b/build-aux/m4/l_atomic.m4
@@ -18,7 +18,7 @@ m4_define([_CHECK_ATOMIC_testbody], [[
int main() {
std::atomic<bool> lock{true};
- std::atomic_exchange(&lock, false);
+ lock.exchange(false);
std::atomic<std::chrono::seconds> t{0s};
t.store(2s);
@@ -34,6 +34,8 @@ m4_define([_CHECK_ATOMIC_testbody], [[
AC_DEFUN([CHECK_ATOMIC], [
AC_LANG_PUSH(C++)
+ TEMP_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
AC_MSG_CHECKING([whether std::atomic can be used without link library])
@@ -51,5 +53,6 @@ AC_DEFUN([CHECK_ATOMIC], [
])
])
+ CXXFLAGS="$TEMP_CXXFLAGS"
AC_LANG_POP
])
diff --git a/build_msvc/README.md b/build_msvc/README.md
index 7feee6b766..b9bebd369c 100644
--- a/build_msvc/README.md
+++ b/build_msvc/README.md
@@ -3,7 +3,9 @@ Building Bitcoin Core with Visual Studio
Introduction
---------------------
-Solution and project files to build Bitcoin Core with `msbuild` or Visual Studio can be found in the `build_msvc` directory. The build has been tested with Visual Studio 2019 (building with earlier versions of Visual Studio should not be expected to work).
+Visual Studio 2022 is minimum required to build Bitcoin Core.
+
+Solution and project files to build with `msbuild` or Visual Studio can be found in the `build_msvc` directory.
To build Bitcoin Core from the command-line, it is sufficient to only install the Visual Studio Build Tools component.
@@ -28,9 +30,9 @@ Qt
---------------------
To build Bitcoin Core with the GUI, a static build of Qt is required.
-1. Download a single ZIP archive of Qt source code from https://download.qt.io/official_releases/qt/ (e.g., [`qt-everywhere-opensource-src-5.15.3.zip`](https://download.qt.io/official_releases/qt/5.15/5.15.3/single/qt-everywhere-opensource-src-5.15.3.zip)), and expand it into a dedicated folder. The following instructions assume that this folder is `C:\dev\qt-source`.
+1. Download a single ZIP archive of Qt source code from https://download.qt.io/official_releases/qt/ (e.g., [`qt-everywhere-opensource-src-5.15.5.zip`](https://download.qt.io/official_releases/qt/5.15/5.15.5/single/qt-everywhere-opensource-src-5.15.5.zip)), and expand it into a dedicated folder. The following instructions assume that this folder is `C:\dev\qt-source`.
-2. Open "x64 Native Tools Command Prompt for VS 2019", and input the following commands:
+2. Open "x64 Native Tools Command Prompt for VS 2022", and input the following commands:
```cmd
cd C:\dev\qt-source
mkdir build
@@ -47,21 +49,21 @@ To build Bitcoin Core without Qt, unload or disable the `bitcoin-qt`, `libbitcoi
Building
---------------------
-1. Use Python to generate `*.vcxproj` from Makefile:
+1. Use Python to generate `*.vcxproj` for the Visual Studio 2022 toolchain from Makefile:
-```
-PS >py -3 msvc-autogen.py
+```cmd
+python build_msvc\msvc-autogen.py
```
2. An optional step is to adjust the settings in the `build_msvc` directory and the `common.init.vcxproj` file. This project file contains settings that are common to all projects such as the runtime library version and target Windows SDK version. The Qt directories can also be set. To specify a non-default path to a static Qt package directory, use the `QTBASEDIR` environment variable.
-3. To build from the command-line with the Visual Studio 2019 toolchain use:
+3. To build from the command-line with the Visual Studio toolchain use:
```cmd
-msbuild -property:Configuration=Release -maxCpuCount -verbosity:minimal bitcoin.sln
+msbuild build_msvc\bitcoin.sln -property:Configuration=Release -maxCpuCount -verbosity:minimal
```
-Alternatively, open the `build_msvc/bitcoin.sln` file in Visual Studio 2019.
+Alternatively, open the `build_msvc/bitcoin.sln` file in Visual Studio.
Security
---------------------
diff --git a/build_msvc/bitcoin_config.h.in b/build_msvc/bitcoin_config.h.in
index b37d536947..5f715282eb 100644
--- a/build_msvc/bitcoin_config.h.in
+++ b/build_msvc/bitcoin_config.h.in
@@ -50,8 +50,8 @@
/* Define this symbol if the consensus lib has been built */
#define HAVE_CONSENSUS_LIB 1
-/* define if the compiler supports basic C++17 syntax */
-#define HAVE_CXX17 1
+/* define if the compiler supports basic C++20 syntax */
+#define HAVE_CXX20 1
/* Define to 1 if you have the declaration of `be16toh', and to 0 if you
don't. */
diff --git a/build_msvc/common.init.vcxproj.in b/build_msvc/common.init.vcxproj.in
index 4c435ea09d..7f623c6296 100644
--- a/build_msvc/common.init.vcxproj.in
+++ b/build_msvc/common.init.vcxproj.in
@@ -87,10 +87,10 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
- <AdditionalOptions>/utf-8 /Zc:__cplusplus /std:c++17 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions>/utf-8 /Zc:__cplusplus /std:c++20 %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4018;4244;4267;4334;4715;4805;4834</DisableSpecificWarnings>
<TreatWarningAsError>true</TreatWarningAsError>
- <PreprocessorDefinitions>DISABLE_DESIGNATED_INITIALIZER_ERRORS;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;ZMQ_STATIC;NOMINMAX;WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;_WIN32_WINNT=0x0601;_WIN32_IE=0x0501;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;ZMQ_STATIC;NOMINMAX;WIN32;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_CONSOLE;_WIN32_WINNT=0x0601;_WIN32_IE=0x0501;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\src;..\..\src\minisketch\include;..\..\src\univalue\include;..\..\src\secp256k1\include;..\..\src\leveldb\include;..\..\src\leveldb\helpers\memenv;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
diff --git a/build_msvc/libsecp256k1_config.h b/build_msvc/libsecp256k1_config.h
index 57f2f144ff..2b1a980e27 100644
--- a/build_msvc/libsecp256k1_config.h
+++ b/build_msvc/libsecp256k1_config.h
@@ -8,23 +8,6 @@
#define BITCOIN_LIBSECP256K1_CONFIG_H
#undef USE_ASM_X86_64
-#undef USE_ENDOMORPHISM
-#undef USE_FIELD_10X26
-#undef USE_FIELD_5X52
-#undef USE_FIELD_INV_BUILTIN
-#undef USE_FIELD_INV_NUM
-#undef USE_NUM_GMP
-#undef USE_NUM_NONE
-#undef USE_SCALAR_4X64
-#undef USE_SCALAR_8X32
-#undef USE_SCALAR_INV_BUILTIN
-#undef USE_SCALAR_INV_NUM
-
-#define USE_NUM_NONE 1
-#define USE_FIELD_INV_BUILTIN 1
-#define USE_SCALAR_INV_BUILTIN 1
-#define USE_FIELD_10X26 1
-#define USE_SCALAR_8X32 1
#define ECMULT_GEN_PREC_BITS 4
#define ECMULT_WINDOW_SIZE 15
diff --git a/build_msvc/msvc-autogen.py b/build_msvc/msvc-autogen.py
index 819fe1b7ae..ae48a52a2f 100755
--- a/build_msvc/msvc-autogen.py
+++ b/build_msvc/msvc-autogen.py
@@ -9,7 +9,7 @@ import argparse
from shutil import copyfile
SOURCE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'src'))
-DEFAULT_PLATFORM_TOOLSET = R'v142'
+DEFAULT_PLATFORM_TOOLSET = R'v143'
libs = [
'libbitcoin_cli',
@@ -93,7 +93,7 @@ def set_properties(vcxproj_filename, placeholder, content):
def main():
parser = argparse.ArgumentParser(description='Bitcoin-core msbuild configuration initialiser.')
parser.add_argument('-toolset', nargs='?', default=DEFAULT_PLATFORM_TOOLSET,
- help='Optionally sets the msbuild platform toolset, e.g. v142 for Visual Studio 2019.'
+ help='Optionally sets the msbuild platform toolset, e.g. v143 for Visual Studio 2022.'
' default is %s.'%DEFAULT_PLATFORM_TOOLSET)
args = parser.parse_args()
set_properties(os.path.join(SOURCE_DIR, '../build_msvc/common.init.vcxproj'), '@TOOLSET@', args.toolset)
diff --git a/ci/lint/06_script.sh b/ci/lint/06_script.sh
index 1f14dd079f..826888b6cc 100755
--- a/ci/lint/06_script.sh
+++ b/ci/lint/06_script.sh
@@ -9,7 +9,12 @@ export LC_ALL=C
GIT_HEAD=$(git rev-parse HEAD)
if [ -n "$CIRRUS_PR" ]; then
COMMIT_RANGE="${CIRRUS_BASE_SHA}..$GIT_HEAD"
+ echo
+ git log --no-merges --oneline "$COMMIT_RANGE"
+ echo
test/lint/commit-script-check.sh "$COMMIT_RANGE"
+else
+ COMMIT_RANGE="SKIP_EMPTY_NOT_A_PR"
fi
export COMMIT_RANGE
@@ -31,11 +36,8 @@ if [ "$CIRRUS_REPO_FULL_NAME" = "bitcoin/bitcoin" ] && [ "$CIRRUS_PR" = "" ] ; t
git log HEAD~10 -1 --format='%H' > ./contrib/verify-commits/trusted-sha512-root-commit
git log HEAD~10 -1 --format='%H' > ./contrib/verify-commits/trusted-git-root
mapfile -t KEYS < contrib/verify-commits/trusted-keys
+ git config user.email "ci@ci.ci"
+ git config user.name "ci"
${CI_RETRY_EXE} gpg --keyserver hkps://keys.openpgp.org --recv-keys "${KEYS[@]}" &&
./contrib/verify-commits/verify-commits.py;
fi
-
-if [ -n "$COMMIT_RANGE" ]; then
- echo
- git log --no-merges --oneline "$COMMIT_RANGE"
-fi
diff --git a/ci/test/00_setup_env_native_asan.sh b/ci/test/00_setup_env_native_asan.sh
index 69883e3609..4f1792a9f0 100755
--- a/ci/test/00_setup_env_native_asan.sh
+++ b/ci/test/00_setup_env_native_asan.sh
@@ -6,9 +6,14 @@
export LC_ALL=C.UTF-8
+# We install an up-to-date 'bpfcc-tools' package from an untrusted PPA.
+# This can be dropped with the next Ubuntu or Debian release that includes up-to-date packages.
+# See the if-then in ci/test/04_install.sh too.
+export ADD_UNTRUSTED_BPFCC_PPA=true
+
export CONTAINER_NAME=ci_native_asan
-export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libsqlite3-dev"
-export DOCKER_NAME_TAG=ubuntu:22.04
+export PACKAGES="systemtap-sdt-dev bpfcc-tools clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libevent-dev bsdmainutils libboost-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libsqlite3-dev"
+export DOCKER_NAME_TAG=ubuntu:22.04 # May not run in docker unless --enable-usdt is dropped
export NO_DEPENDS=1
export GOAL="install"
-export BITCOIN_CONFIG="--enable-c++20 --enable-zmq --with-incompatible-bdb --with-gui=qt5 CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' --with-sanitizers=address,integer,undefined CC=clang CXX=clang++"
+export BITCOIN_CONFIG="--enable-usdt --enable-zmq --with-incompatible-bdb --with-gui=qt5 CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' --with-sanitizers=address,integer,undefined CC=clang CXX=clang++"
diff --git a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh
index 9477fb2d9f..97c530e19e 100755
--- a/ci/test/00_setup_env_native_fuzz_with_valgrind.sh
+++ b/ci/test/00_setup_env_native_fuzz_with_valgrind.sh
@@ -16,5 +16,5 @@ export RUN_FUZZ_TESTS=true
export FUZZ_TESTS_CONFIG="--valgrind"
export GOAL="install"
# Temporarily pin dwarf 4, until valgrind can understand clang's dwarf 5
-export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer CC=clang CXX=clang++ CXXFLAGS='-fdebug-default-version=4'"
+export BITCOIN_CONFIG="--enable-fuzz --with-sanitizers=fuzzer CC=clang CXX=clang++ CFLAGS='-gdwarf-4' CXXFLAGS='-gdwarf-4'"
export CCACHE_SIZE=200M
diff --git a/ci/test/00_setup_env_native_qt5.sh b/ci/test/00_setup_env_native_qt5.sh
index f399e43612..8a6ea62d5c 100755
--- a/ci/test/00_setup_env_native_qt5.sh
+++ b/ci/test/00_setup_env_native_qt5.sh
@@ -14,6 +14,6 @@ export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude fe
export RUN_UNIT_TESTS_SEQUENTIAL="true"
export RUN_UNIT_TESTS="false"
export GOAL="install"
-export PREVIOUS_RELEASES_TO_DOWNLOAD="v0.14.3 v0.15.2 v0.16.3 v0.17.2 v0.18.1 v0.19.1 v0.20.1 v0.21.0 v22.0 v23.0"
+export DOWNLOAD_PREVIOUS_RELEASES="true"
export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-reduce-exports \
--enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\" CC=gcc-8 CXX=g++-8"
diff --git a/ci/test/00_setup_env_native_tidy.sh b/ci/test/00_setup_env_native_tidy.sh
index e4d3468473..11a12e336a 100755
--- a/ci/test/00_setup_env_native_tidy.sh
+++ b/ci/test/00_setup_env_native_tidy.sh
@@ -15,5 +15,5 @@ export RUN_FUNCTIONAL_TESTS=false
export RUN_FUZZ_TESTS=false
export RUN_TIDY=true
export GOAL="install"
-export BITCOIN_CONFIG="CC=clang CXX=clang++ --with-incompatible-bdb --disable-hardening CFLAGS='-O0 -g0' CXXFLAGS='-O0 -g0'"
+export BITCOIN_CONFIG="CC=clang CXX=clang++ --enable-c++20 --with-incompatible-bdb --disable-hardening CFLAGS='-O0 -g0' CXXFLAGS='-O0 -g0'"
export CCACHE_SIZE=200M
diff --git a/ci/test/00_setup_env_native_valgrind.sh b/ci/test/00_setup_env_native_valgrind.sh
index 7b714dff5c..d8c08fca39 100755
--- a/ci/test/00_setup_env_native_valgrind.sh
+++ b/ci/test/00_setup_env_native_valgrind.sh
@@ -14,4 +14,4 @@ export NO_DEPENDS=1
export TEST_RUNNER_EXTRA="--nosandbox --exclude feature_init,rpc_bind,feature_bind_extra" # Excluded for now, see https://github.com/bitcoin/bitcoin/issues/17765#issuecomment-602068547
export GOAL="install"
# Temporarily pin dwarf 4, until valgrind can understand clang's dwarf 5
-export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no CC=clang CXX=clang++ CXXFLAGS='-fdebug-default-version=4'" # TODO enable GUI
+export BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --with-gui=no CC=clang CXX=clang++ CFLAGS='-gdwarf-4' CXXFLAGS='-gdwarf-4'" # TODO enable GUI
diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh
index ba05eb631f..a4f1a8a7ff 100755
--- a/ci/test/04_install.sh
+++ b/ci/test/04_install.sh
@@ -62,6 +62,14 @@ if [[ $DOCKER_NAME_TAG == *centos* ]]; then
${CI_RETRY_EXE} CI_EXEC dnf -y install epel-release
${CI_RETRY_EXE} CI_EXEC dnf -y --allowerasing install "$DOCKER_PACKAGES" "$PACKAGES"
elif [ "$CI_USE_APT_INSTALL" != "no" ]; then
+ if [[ "${ADD_UNTRUSTED_BPFCC_PPA}" == "true" ]]; then
+ # Ubuntu 22.04 LTS and Debian 11 both have an outdated bpfcc-tools packages.
+ # The iovisor PPA is outdated as well. The next Ubuntu and Debian releases will contain updated
+ # packages. Meanwhile, use an untrusted PPA to install an up-to-date version of the bpfcc-tools
+ # package.
+ # TODO: drop this once we can use newer images in GCE
+ CI_EXEC add-apt-repository ppa:hadret/bpfcc
+ fi
${CI_RETRY_EXE} CI_EXEC apt-get update
${CI_RETRY_EXE} CI_EXEC apt-get install --no-install-recommends --no-upgrade -y "$PACKAGES" "$DOCKER_PACKAGES"
fi
diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh
index f3da6b4f31..ef3dff86ca 100755
--- a/ci/test/05_before_script.sh
+++ b/ci/test/05_before_script.sh
@@ -47,6 +47,6 @@ if [ -z "$NO_DEPENDS" ]; then
fi
CI_EXEC "$SHELL_OPTS" make "$MAKEJOBS" -C depends HOST="$HOST" "$DEP_OPTS" LOG=1
fi
-if [ -n "$PREVIOUS_RELEASES_TO_DOWNLOAD" ]; then
- CI_EXEC test/get_previous_releases.py -b -t "$PREVIOUS_RELEASES_DIR" "${PREVIOUS_RELEASES_TO_DOWNLOAD}"
+if [ "$DOWNLOAD_PREVIOUS_RELEASES" = "true" ]; then
+ CI_EXEC test/get_previous_releases.py -b -t "$PREVIOUS_RELEASES_DIR"
fi
diff --git a/ci/test/06_script_a.sh b/ci/test/06_script_a.sh
index 218f5eeb63..13693a2ecf 100755
--- a/ci/test/06_script_a.sh
+++ b/ci/test/06_script_a.sh
@@ -11,16 +11,19 @@ if [ -z "$NO_WERROR" ]; then
BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} --enable-werror"
fi
+CI_EXEC "ccache --zero-stats --max-size=$CCACHE_SIZE"
+PRINT_CCACHE_STATISTICS="ccache --version | head -n 1 && ccache --show-stats"
+
if [ -n "$ANDROID_TOOLS_URL" ]; then
CI_EXEC make distclean || true
CI_EXEC ./autogen.sh
CI_EXEC ./configure "$BITCOIN_CONFIG_ALL" "$BITCOIN_CONFIG" || ( (CI_EXEC cat config.log) && false)
CI_EXEC "make $MAKEJOBS && cd src/qt && ANDROID_HOME=${ANDROID_HOME} ANDROID_NDK_HOME=${ANDROID_NDK_HOME} make apk"
+ CI_EXEC "${PRINT_CCACHE_STATISTICS}"
exit 0
fi
BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} --enable-external-signer --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib"
-CI_EXEC "ccache --zero-stats --max-size=$CCACHE_SIZE"
if [ -n "$CONFIG_SHELL" ]; then
CI_EXEC "$CONFIG_SHELL" -c "./autogen.sh"
@@ -57,6 +60,6 @@ fi
CI_EXEC "${MAYBE_BEAR}" "${MAYBE_TOKEN}" make "$MAKEJOBS" "$GOAL" || ( echo "Build failure. Verbose build follows." && CI_EXEC make "$GOAL" V=1 ; false )
-CI_EXEC "ccache --version | head -n 1 && ccache --show-stats"
+CI_EXEC "${PRINT_CCACHE_STATISTICS}"
CI_EXEC du -sh "${DEPENDS_DIR}"/*/
CI_EXEC du -sh "${PREVIOUS_RELEASES_DIR}"
diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh
index bdb68e0f6f..5bdb392ba3 100755
--- a/ci/test/06_script_b.sh
+++ b/ci/test/06_script_b.sh
@@ -35,17 +35,39 @@ if [ "$RUN_FUNCTIONAL_TESTS" = "true" ]; then
fi
if [ "${RUN_TIDY}" = "true" ]; then
+ set -eo pipefail
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/src/"
- CI_EXEC run-clang-tidy "${MAKEJOBS}"
+ ( CI_EXEC run-clang-tidy -quiet "${MAKEJOBS}" ) | grep -C5 "error"
export P_CI_DIR="${BASE_BUILD_DIR}/bitcoin-$HOST/"
CI_EXEC "python3 ${DIR_IWYU}/include-what-you-use/iwyu_tool.py"\
" src/compat"\
+ " src/dbwrapper.cpp"\
" src/init"\
+ " src/kernel"\
+ " src/node/chainstate.cpp"\
+ " src/node/mempool_args.cpp"\
+ " src/node/validation_cache_args.cpp"\
" src/policy/feerate.cpp"\
" src/policy/packages.cpp"\
" src/policy/settings.cpp"\
+ " src/primitives/transaction.cpp"\
" src/rpc/fees.cpp"\
" src/rpc/signmessage.cpp"\
+ " src/test/fuzz/txorphan.cpp"\
+ " src/threadinterrupt.cpp"\
+ " src/util/bip32.cpp"\
+ " src/util/bytevectorhash.cpp"\
+ " src/util/error.cpp"\
+ " src/util/getuniquepath.cpp"\
+ " src/util/hasher.cpp"\
+ " src/util/message.cpp"\
+ " src/util/moneystr.cpp"\
+ " src/util/serfloat.cpp"\
+ " src/util/spanparsing.cpp"\
+ " src/util/strencodings.cpp"\
+ " src/util/string.cpp"\
+ " src/util/syserror.cpp"\
+ " src/util/url.cpp"\
" -p . ${MAKEJOBS} -- -Xiwyu --cxx17ns -Xiwyu --mapping_file=${BASE_BUILD_DIR}/bitcoin-$HOST/contrib/devtools/iwyu/bitcoin.core.imp"
fi
diff --git a/ci/test/wrap-qemu.sh b/ci/test/wrap-qemu.sh
index fcd56f533e..eb31edbce8 100755
--- a/ci/test/wrap-qemu.sh
+++ b/ci/test/wrap-qemu.sh
@@ -6,7 +6,7 @@
export LC_ALL=C.UTF-8
-for b_name in {"${BASE_OUTDIR}/bin"/*,src/secp256k1/*tests,src/minisketch/test{,-verify},src/univalue/{no_nul,test_json,unitester,object}}; do
+for b_name in {"${BASE_OUTDIR}/bin"/*,src/secp256k1/*tests,src/minisketch/test{,-verify},src/univalue/{test_json,unitester,object}}; do
# shellcheck disable=SC2044
for b in $(find "${BASE_ROOT_DIR}" -executable -type f -name "$(basename "$b_name")"); do
echo "Wrap $b ..."
diff --git a/ci/test/wrap-wine.sh b/ci/test/wrap-wine.sh
index 525db9eded..1662f8f6a3 100755
--- a/ci/test/wrap-wine.sh
+++ b/ci/test/wrap-wine.sh
@@ -6,7 +6,7 @@
export LC_ALL=C.UTF-8
-for b_name in {"${BASE_OUTDIR}/bin"/*,src/secp256k1/*tests,src/minisketch/test{,-verify},src/univalue/{no_nul,test_json,unitester,object}}.exe; do
+for b_name in {"${BASE_OUTDIR}/bin"/*,src/secp256k1/*tests,src/minisketch/test{,-verify},src/univalue/{test_json,unitester,object}}.exe; do
# shellcheck disable=SC2044
for b in $(find "${BASE_ROOT_DIR}" -executable -type f -name "$(basename "$b_name")"); do
if (file "$b" | grep "Windows"); then
diff --git a/configure.ac b/configure.ac
index 163f69988e..87dd0dc81e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,9 +1,9 @@
AC_PREREQ([2.69])
-define(_CLIENT_VERSION_MAJOR, 23)
-define(_CLIENT_VERSION_MINOR, 99)
-define(_CLIENT_VERSION_BUILD, 0)
+define(_CLIENT_VERSION_MAJOR, 24)
+define(_CLIENT_VERSION_MINOR, 0)
+define(_CLIENT_VERSION_BUILD, 1)
define(_CLIENT_VERSION_RC, 0)
-define(_CLIENT_VERSION_IS_RELEASE, false)
+define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2022)
define(_COPYRIGHT_HOLDERS,[The %s developers])
define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Bitcoin Core]])
@@ -19,8 +19,19 @@ if test "$PKG_CONFIG" = ""; then
AC_MSG_ERROR([pkg-config not found])
fi
+# When compiling with depends, the `PKG_CONFIG_PATH` and `PKG_CONFIG_LIBDIR` variables,
+# being set in a `config.site` file, are not exported to let the `--config-cache` option
+# work properly.
+if test -n "$PKG_CONFIG_PATH"; then
+ PKG_CONFIG="env PKG_CONFIG_PATH=$PKG_CONFIG_PATH $PKG_CONFIG"
+fi
+if test -n "$PKG_CONFIG_LIBDIR"; then
+ PKG_CONFIG="env PKG_CONFIG_LIBDIR=$PKG_CONFIG_LIBDIR $PKG_CONFIG"
+fi
+
BITCOIN_DAEMON_NAME=bitcoind
BITCOIN_GUI_NAME=bitcoin-qt
+BITCOIN_TEST_NAME=test_bitcoin
BITCOIN_CLI_NAME=bitcoin-cli
BITCOIN_TX_NAME=bitcoin-tx
BITCOIN_UTIL_NAME=bitcoin-util
@@ -87,9 +98,6 @@ else
AX_CXX_COMPILE_STDCXX([20], [noext], [mandatory])
fi
-dnl Check if -latomic is required for <std::atomic>
-CHECK_ATOMIC
-
dnl check if additional link flags are required for std::filesystem
CHECK_FILESYSTEM
@@ -325,7 +333,7 @@ AC_ARG_ENABLE([werror],
[enable_werror=no])
AC_ARG_ENABLE([external-signer],
- [AS_HELP_STRING([--enable-external-signer],[compile external signer support (default is yes, requires Boost::Process)])],
+ [AS_HELP_STRING([--enable-external-signer],[compile external signer support (default is auto, requires Boost::Process)])],
[use_external_signer=$enableval],
[use_external_signer=auto])
@@ -511,7 +519,7 @@ if test "$enable_clmul" = "yes"; then
fi
TEMP_CXXFLAGS="$CXXFLAGS"
-CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS"
+CXXFLAGS="$SSE42_CXXFLAGS $CXXFLAGS"
AC_MSG_CHECKING([for SSE4.2 intrinsics])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>
@@ -533,7 +541,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
CXXFLAGS="$TEMP_CXXFLAGS"
TEMP_CXXFLAGS="$CXXFLAGS"
-CXXFLAGS="$CXXFLAGS $SSE41_CXXFLAGS"
+CXXFLAGS="$SSE41_CXXFLAGS $CXXFLAGS"
AC_MSG_CHECKING([for SSE4.1 intrinsics])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>
@@ -548,7 +556,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
CXXFLAGS="$TEMP_CXXFLAGS"
TEMP_CXXFLAGS="$CXXFLAGS"
-CXXFLAGS="$CXXFLAGS $AVX2_CXXFLAGS"
+CXXFLAGS="$AVX2_CXXFLAGS $CXXFLAGS"
AC_MSG_CHECKING([for AVX2 intrinsics])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>
@@ -563,7 +571,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
CXXFLAGS="$TEMP_CXXFLAGS"
TEMP_CXXFLAGS="$CXXFLAGS"
-CXXFLAGS="$CXXFLAGS $X86_SHANI_CXXFLAGS"
+CXXFLAGS="$X86_SHANI_CXXFLAGS $CXXFLAGS"
AC_MSG_CHECKING([for x86 SHA-NI intrinsics])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>
@@ -584,7 +592,7 @@ AX_CHECK_COMPILE_FLAG([-march=armv8-a+crc+crypto], [ARM_CRC_CXXFLAGS="-march=arm
AX_CHECK_COMPILE_FLAG([-march=armv8-a+crc+crypto], [ARM_SHANI_CXXFLAGS="-march=armv8-a+crc+crypto"], [], [$CXXFLAG_WERROR])
TEMP_CXXFLAGS="$CXXFLAGS"
-CXXFLAGS="$CXXFLAGS $ARM_CRC_CXXFLAGS"
+CXXFLAGS="$ARM_CRC_CXXFLAGS $CXXFLAGS"
AC_MSG_CHECKING([for ARMv8 CRC32 intrinsics])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <arm_acle.h>
@@ -603,7 +611,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
CXXFLAGS="$TEMP_CXXFLAGS"
TEMP_CXXFLAGS="$CXXFLAGS"
-CXXFLAGS="$CXXFLAGS $ARM_SHANI_CXXFLAGS"
+CXXFLAGS="$ARM_SHANI_CXXFLAGS $CXXFLAGS"
AC_MSG_CHECKING([for ARMv8 SHA-NI intrinsics])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <arm_acle.h>
@@ -738,6 +746,16 @@ case $host in
dnl It's safe to add these paths even if the functionality is disabled by
dnl the user (--without-wallet or --without-gui for example).
+ dnl Homebrew may create symlinks in /usr/local/include for some packages.
+ dnl Because MacOS's clang internally adds "-I /usr/local/include" to its search
+ dnl paths, this will negate efforts to use -isystem for those packages, as they
+ dnl will be found first in /usr/local. Use the internal "-internal-isystem"
+ dnl option to system-ify all /usr/local/include paths without adding it to the list
+ dnl of search paths in case it's not already there.
+ if test "$suppress_external_warnings" != "no"; then
+ AX_CHECK_PREPROC_FLAG([-Xclang -internal-isystem/usr/local/include], [CORE_CPPFLAGS="$CORE_CPPFLAGS -Xclang -internal-isystem/usr/local/include"], [], [$CXXFLAG_WERROR])
+ fi
+
if test "$use_bdb" != "no" && $BREW list --versions berkeley-db@4 >/dev/null && test "$BDB_CFLAGS" = "" && test "$BDB_LIBS" = ""; then
bdb_prefix=$($BREW --prefix berkeley-db@4 2>/dev/null)
dnl This must precede the call to BITCOIN_FIND_BDB48 below.
@@ -745,10 +763,6 @@ case $host in
BDB_LIBS="-L$bdb_prefix/lib -ldb_cxx-4.8"
fi
- if test "$use_sqlite" != "no" && $BREW list --versions sqlite3 >/dev/null; then
- export PKG_CONFIG_PATH="$($BREW --prefix sqlite3 2>/dev/null)/lib/pkgconfig:$PKG_CONFIG_PATH"
- fi
-
if $BREW list --versions qt@5 >/dev/null; then
export PKG_CONFIG_PATH="$($BREW --prefix qt@5 2>/dev/null)/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
@@ -887,6 +901,9 @@ AC_C_BIGENDIAN
dnl Check for pthread compile/link requirements
AX_PTHREAD
+dnl Check if -latomic is required for <std::atomic>
+CHECK_ATOMIC
+
dnl The following macro will add the necessary defines to bitcoin-config.h, but
dnl they also need to be passed down to any subprojects. Pull the results out of
dnl the cache and add them to CPPFLAGS.
@@ -1303,6 +1320,7 @@ if test "$enable_fuzz" = "yes"; then
bitcoin_enable_qt_test=no
bitcoin_enable_qt_dbus=no
use_bench=no
+ use_tests=no
use_external_signer=no
use_upnp=no
use_natpmp=no
@@ -1460,6 +1478,11 @@ if test "$use_boost" = "yes"; then
dnl we don't use multi_index serialization
BOOST_CPPFLAGS="$BOOST_CPPFLAGS -DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION"
+ dnl Prevent use of std::unary_function, which was removed in C++17,
+ dnl and will generate warnings with newer compilers.
+ dnl See: https://github.com/boostorg/container_hash/issues/22.
+ BOOST_CPPFLAGS="$BOOST_CPPFLAGS -DBOOST_NO_CXX98_FUNCTION_BASE"
+
if test "$enable_debug" = "yes" || test "$enable_fuzz" = "yes"; then
BOOST_CPPFLAGS="$BOOST_CPPFLAGS -DBOOST_MULTI_INDEX_ENABLE_SAFE_MODE"
fi
@@ -1559,7 +1582,7 @@ fi
dnl libevent check
use_libevent=no
-if test "$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench" != "nonononono"; then
+if test "$build_bitcoin_cli$build_bitcoind$bitcoin_enable_qt$enable_fuzz_binary$use_tests$use_bench" != "nononononono"; then
PKG_CHECK_MODULES([EVENT], [libevent >= 2.1.8], [use_libevent=yes], [AC_MSG_ERROR([libevent version 2.1.8 or greater not found.])])
if test "$TARGET_OS" != "windows"; then
PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads >= 2.1.8], [], [AC_MSG_ERROR([libevent_pthreads version 2.1.8 or greater not found.])])
@@ -1678,11 +1701,12 @@ AM_CONDITIONAL([BUILD_BITCOIN_UTIL], [test $build_bitcoin_util = "yes"])
AC_MSG_RESULT($build_bitcoin_util)
AC_MSG_CHECKING([whether to build experimental bitcoin-chainstate])
-if test "$build_experimental_kernel_lib" = "no"; then
-AC_MSG_ERROR([experimental bitcoin-chainstate cannot be built without the experimental bitcoinkernel library. Use --with-experimental-kernel-lib]);
-else
- AM_CONDITIONAL([BUILD_BITCOIN_CHAINSTATE], [test $build_bitcoin_chainstate = "yes"])
+if test "$build_bitcoin_chainstate" = "yes"; then
+ if test "$build_experimental_kernel_lib" = "no"; then
+ AC_MSG_ERROR([experimental bitcoin-chainstate cannot be built without the experimental bitcoinkernel library. Use --with-experimental-kernel-lib]);
+ fi
fi
+AM_CONDITIONAL([BUILD_BITCOIN_CHAINSTATE], [test $build_bitcoin_chainstate = "yes"])
AC_MSG_RESULT($build_bitcoin_chainstate)
AC_MSG_CHECKING([whether to build libraries])
@@ -1846,8 +1870,8 @@ else
AC_MSG_RESULT([no])
fi
-if test "$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_bench$use_tests" = "nononononononono"; then
- AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui --enable-bench or --enable-tests])
+if test "$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$enable_fuzz_binary$use_bench$use_tests" = "nonononononononono"; then
+ AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui --enable-fuzz(-binary) --enable-bench or --enable-tests])
fi
AM_CONDITIONAL([TARGET_DARWIN], [test "$TARGET_OS" = "darwin"])
@@ -1901,6 +1925,7 @@ AC_SUBST(COPYRIGHT_HOLDERS_SUBSTITUTION, "_COPYRIGHT_HOLDERS_SUBSTITUTION")
AC_SUBST(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL")
AC_SUBST(BITCOIN_DAEMON_NAME)
AC_SUBST(BITCOIN_GUI_NAME)
+AC_SUBST(BITCOIN_TEST_NAME)
AC_SUBST(BITCOIN_CLI_NAME)
AC_SUBST(BITCOIN_TX_NAME)
AC_SUBST(BITCOIN_UTIL_NAME)
@@ -1972,6 +1997,9 @@ AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py])
AC_CONFIG_LINKS([test/fuzz/test_runner.py:test/fuzz/test_runner.py])
AC_CONFIG_LINKS([test/util/test_runner.py:test/util/test_runner.py])
AC_CONFIG_LINKS([test/util/rpcauth-test.py:test/util/rpcauth-test.py])
+AC_CONFIG_LINKS([src/qt/Makefile:src/qt/Makefile])
+AC_CONFIG_LINKS([src/qt/test/Makefile:src/qt/test/Makefile])
+AC_CONFIG_LINKS([src/test/Makefile:src/test/Makefile])
dnl boost's m4 checks do something really nasty: they export these vars. As a
dnl result, they leak into secp256k1's configure and crazy things happen.
@@ -2043,5 +2071,6 @@ echo " CPPFLAGS = $DEBUG_CPPFLAGS $HARDENED_CPPFLAGS $CORE_CPPFLAGS $CPP
echo " CXX = $CXX"
echo " CXXFLAGS = $LTO_CXXFLAGS $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $WARN_CXXFLAGS $NOWARN_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CORE_CXXFLAGS $CXXFLAGS"
echo " LDFLAGS = $LTO_LDFLAGS $PTHREAD_LIBS $HARDENED_LDFLAGS $GPROF_LDFLAGS $CORE_LDFLAGS $LDFLAGS"
+echo " AR = $AR"
echo " ARFLAGS = $ARFLAGS"
echo
diff --git a/contrib/builder-keys/keys.txt b/contrib/builder-keys/keys.txt
index c70069b440..f8377cce33 100644
--- a/contrib/builder-keys/keys.txt
+++ b/contrib/builder-keys/keys.txt
@@ -19,6 +19,7 @@ BF6273FAEF7CC0BA1F562E50989F6B3048A116B5 Dev Random (devrandom)
D35176BE9264832E4ACA8986BF0792FBE95DC863 fivepiece (fivepiece)
6F993B250557E7B016ADE5713BDCDA2D87A881D9 Fuzzbawls (Fuzzbawls)
01CDF4627A3B88AAE4A571C87588242FBE38D3A8 Gavin Andresen (gavinandresen)
+6B002C6EA3F91B1B0DF0C9BC8F617F1200A6D25C Gloria Zhao (glozow)
D1DBF2C4B96F2DEBF4C16654410108112E7EA81F Hennadii Stepanov (hebasto)
A2FD494D0021AA9B4FA58F759102B7AE654A4A5A Ilyas Ridhuan (IlyasRidhuan)
2688F5A9A4BE0F295E921E8A25F27A38A47AD566 James O'Beirne (jamesob)
diff --git a/contrib/devtools/iwyu/bitcoin.core.imp b/contrib/devtools/iwyu/bitcoin.core.imp
index ce7786f58c..919ffab102 100644
--- a/contrib/devtools/iwyu/bitcoin.core.imp
+++ b/contrib/devtools/iwyu/bitcoin.core.imp
@@ -3,4 +3,5 @@
{ include: [ "<bits/termios-c_lflag.h>", private, "<termios.h>", public ] },
{ include: [ "<bits/termios-struct.h>", private, "<termios.h>", public ] },
{ include: [ "<bits/termios-tcflow.h>", private, "<termios.h>", public ] },
+ { include: [ "<bits/chrono.h>", private, "<chrono>", public ] },
]
diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py
index 23d29af3f1..4b1cceb57c 100755
--- a/contrib/devtools/symbol-check.py
+++ b/contrib/devtools/symbol-check.py
@@ -35,7 +35,6 @@ import lief #type:ignore
MAX_VERSIONS = {
'GCC': (4,8,0),
'GLIBC': {
- lief.ELF.ARCH.i386: (2,18),
lief.ELF.ARCH.x86_64: (2,18),
lief.ELF.ARCH.ARM: (2,18),
lief.ELF.ARCH.AARCH64:(2,18),
@@ -45,8 +44,6 @@ MAX_VERSIONS = {
'LIBATOMIC': (1,0),
'V': (0,5,0), # xkb (bitcoin-qt only)
}
-# See here for a description of _IO_stdin_used:
-# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634261#109
# Ignore symbols that are exported as part of every executable
IGNORE_EXPORTS = {
@@ -57,9 +54,6 @@ IGNORE_EXPORTS = {
# Expected linker-loader names can be found here:
# https://sourceware.org/glibc/wiki/ABIList?action=recall&rev=16
ELF_INTERPRETER_NAMES: Dict[lief.ELF.ARCH, Dict[lief.ENDIANNESS, str]] = {
- lief.ELF.ARCH.i386: {
- lief.ENDIANNESS.LITTLE: "/lib/ld-linux.so.2",
- },
lief.ELF.ARCH.x86_64: {
lief.ENDIANNESS.LITTLE: "/lib64/ld-linux-x86-64.so.2",
},
diff --git a/contrib/guix/INSTALL.md b/contrib/guix/INSTALL.md
index 68aae18731..a9a41ddff6 100644
--- a/contrib/guix/INSTALL.md
+++ b/contrib/guix/INSTALL.md
@@ -72,11 +72,11 @@ writing (July 2021). Guix is expected to be more widely packaged over time. For
an up-to-date view on Guix's package status/version across distros, please see:
https://repology.org/project/guix/versions
-### Debian 11 (Bullseye)/Ubuntu 21.04 (Hirsute Hippo)
+### Debian / Ubuntu
Guix v1.2.0 is available as a distribution package starting in [Debian
11](https://packages.debian.org/bullseye/guix) and [Ubuntu
-21.04](https://packages.ubuntu.com/hirsute/guix).
+21.04](https://packages.ubuntu.com/search?keywords=guix).
Note that if you intend on using Guix without using any substitutes (more
details [here][security-model]), v1.2.0 has a known problem when building GnuTLS
diff --git a/contrib/guix/README.md b/contrib/guix/README.md
index af5607c710..ed6ac8d589 100644
--- a/contrib/guix/README.md
+++ b/contrib/guix/README.md
@@ -382,7 +382,7 @@ https://ci.guix.gnu.org is automatically used unless the `--no-substitutes` flag
is supplied. This default list of substitute servers is overridable both on a
`guix-daemon` level and when you invoke `guix` commands. See examples below for
the various ways of adding dongcarl's substitute server after having [authorized
-his signing key](#authorize-the-signing-keys).
+his signing key](#step-1-authorize-the-signing-keys).
Change the **default list** of substitute servers by starting `guix-daemon` with
the `--substitute-urls` option (you will likely need to edit your init script):
diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh
index 44c769f463..f39f83d443 100755
--- a/contrib/guix/libexec/build.sh
+++ b/contrib/guix/libexec/build.sh
@@ -196,7 +196,6 @@ make -C depends --jobs="$JOBS" HOST="$HOST" \
x86_64_linux_RANLIB=x86_64-linux-gnu-ranlib \
x86_64_linux_NM=x86_64-linux-gnu-nm \
x86_64_linux_STRIP=x86_64-linux-gnu-strip \
- qt_config_opts_x86_64_linux='-platform linux-g++ -xplatform bitcoin-linux-g++' \
FORCE_USE_SYSTEM_CLANG=1
@@ -223,6 +222,7 @@ CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests --disab
# CFLAGS
HOST_CFLAGS="-O2 -g"
+HOST_CFLAGS+=$(find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;)
case "$HOST" in
*linux*) HOST_CFLAGS+=" -ffile-prefix-map=${PWD}=." ;;
*mingw*) HOST_CFLAGS+=" -fno-ident" ;;
@@ -249,10 +249,6 @@ case "$HOST" in
*powerpc64*) HOST_LDFLAGS="${HOST_LDFLAGS} -Wl,--no-tls-get-addr-optimize" ;;
esac
-case "$HOST" in
- powerpc64-linux-*) HOST_LDFLAGS="${HOST_LDFLAGS} -Wl,-z,noexecstack" ;;
-esac
-
# Make $HOST-specific native binaries from depends available in $PATH
export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
mkdir -p "$DISTSRC"
@@ -372,6 +368,8 @@ mkdir -p "$DISTSRC"
# has not been run before buildling, this file will be a stub
cp "${DISTSRC}/share/examples/bitcoin.conf" "${DISTNAME}/"
+ cp -r "${DISTSRC}/share/rpcauth" "${DISTNAME}/share/"
+
# Finally, deterministically produce {non-,}debug binary tarballs ready
# for release
case "$HOST" in
diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm
index d35ad85e56..8e5c89cc5e 100644
--- a/contrib/guix/manifest.scm
+++ b/contrib/guix/manifest.scm
@@ -21,7 +21,6 @@
(gnu packages llvm)
(gnu packages mingw)
(gnu packages moreutils)
- (gnu packages perl)
(gnu packages pkg-config)
(gnu packages python)
(gnu packages python-crypto)
@@ -78,6 +77,11 @@ http://www.linuxfromscratch.org/hlfs/view/development/chapter05/gcc-pass1.html"
(("-rpath=") "-rpath-link="))
#t))))))))
+(define building-on (string-append (list-ref (string-split (%current-system) #\-) 0) "-guix-linux-gnu"))
+
+(define (explicit-cross-configure package)
+ (package-with-extra-configure-variable package "--build" building-on))
+
(define (make-cross-toolchain target
base-gcc-for-libc
base-kernel-headers
@@ -87,9 +91,9 @@ http://www.linuxfromscratch.org/hlfs/view/development/chapter05/gcc-pass1.html"
(let* ((xbinutils (cross-binutils target))
;; 1. Build a cross-compiling gcc without targeting any libc, derived
;; from BASE-GCC-FOR-LIBC
- (xgcc-sans-libc (cross-gcc target
- #:xgcc base-gcc-for-libc
- #:xbinutils xbinutils))
+ (xgcc-sans-libc (explicit-cross-configure (cross-gcc target
+ #:xgcc base-gcc-for-libc
+ #:xbinutils xbinutils)))
;; 2. Build cross-compiled kernel headers with XGCC-SANS-LIBC, derived
;; from BASE-KERNEL-HEADERS
(xkernel (cross-kernel-headers target
@@ -98,17 +102,17 @@ http://www.linuxfromscratch.org/hlfs/view/development/chapter05/gcc-pass1.html"
xbinutils))
;; 3. Build a cross-compiled libc with XGCC-SANS-LIBC and XKERNEL,
;; derived from BASE-LIBC
- (xlibc (cross-libc target
- base-libc
- xgcc-sans-libc
- xbinutils
- xkernel))
+ (xlibc (explicit-cross-configure (cross-libc target
+ base-libc
+ xgcc-sans-libc
+ xbinutils
+ xkernel)))
;; 4. Build a cross-compiling gcc targeting XLIBC, derived from
;; BASE-GCC
- (xgcc (cross-gcc target
- #:xgcc base-gcc
- #:xbinutils xbinutils
- #:libc xlibc)))
+ (xgcc (explicit-cross-configure (cross-gcc target
+ #:xgcc base-gcc
+ #:xbinutils xbinutils
+ #:libc xlibc))))
;; Define a meta-package that propagates the resulting XBINUTILS, XLIBC, and
;; XGCC
(package
@@ -132,26 +136,19 @@ chain for " target " development."))
(define base-gcc gcc-10)
(define base-linux-kernel-headers linux-libre-headers-5.15)
-;; Building glibc with stack smashing protector first landed in glibc 2.25, use
-;; this function to disable for older glibcs
-;;
-;; From glibc 2.25 changelog:
-;;
-;; * Most of glibc can now be built with the stack smashing protector enabled.
-;; It is recommended to build glibc with --enable-stack-protector=strong.
-;; Implemented by Nick Alcock (Oracle).
-(define (make-glibc-without-ssp xglibc)
- (package-with-extra-configure-variable
- (package-with-extra-configure-variable
- xglibc "libc_cv_ssp" "no")
- "libc_cv_ssp_strong" "no"))
+;; https://gcc.gnu.org/install/configure.html
+(define (hardened-gcc gcc)
+ (package-with-extra-configure-variable (
+ package-with-extra-configure-variable gcc
+ "--enable-default-ssp" "yes")
+ "--enable-default-pie" "yes"))
(define* (make-bitcoin-cross-toolchain target
#:key
(base-gcc-for-libc base-gcc)
(base-kernel-headers base-linux-kernel-headers)
- (base-libc (make-glibc-without-ssp (make-glibc-without-werror glibc-2.24)))
- (base-gcc (make-gcc-rpath-link base-gcc)))
+ (base-libc (make-glibc-with-bind-now (make-glibc-without-werror glibc-2.24)))
+ (base-gcc (make-gcc-rpath-link (hardened-gcc base-gcc))))
"Convenience wrapper around MAKE-CROSS-TOOLCHAIN with default values
desirable for building Bitcoin Core release binaries."
(make-cross-toolchain target
@@ -161,7 +158,10 @@ desirable for building Bitcoin Core release binaries."
base-gcc))
(define (make-gcc-with-pthreads gcc)
- (package-with-extra-configure-variable gcc "--enable-threads" "posix"))
+ (package-with-extra-configure-variable
+ (package-with-extra-patches gcc
+ (search-our-patches "gcc-10-remap-guix-store.patch"))
+ "--enable-threads" "posix"))
(define (make-mingw-w64-cross-gcc cross-gcc)
(package-with-extra-patches cross-gcc
@@ -198,12 +198,17 @@ chain for " target " development."))
(define (make-nsis-for-gcc-10 base-nsis)
(package-with-extra-patches base-nsis
- (search-our-patches "nsis-gcc-10-memmove.patch")))
+ (search-our-patches "nsis-gcc-10-memmove.patch"
+ "nsis-disable-installer-reloc.patch")))
+
+(define (fix-ppc64-nx-default lief)
+ (package-with-extra-patches lief
+ (search-our-patches "lief-fix-ppc64-nx-default.patch")))
(define-public lief
(package
(name "python-lief")
- (version "0.12.0")
+ (version "0.12.1")
(source
(origin
(method git-fetch)
@@ -213,8 +218,15 @@ chain for " target " development."))
(file-name (git-file-name name version))
(sha256
(base32
- "026jchj56q25v6gc0754dj9cj5hz5zaza8ij93y5ga94w20kzm9q"))))
+ "1xzbh3bxy4rw1yamnx68da1v5s56ay4g081cyamv67256g0qy2i1"))))
(build-system python-build-system)
+ (arguments
+ `(#:phases
+ (modify-phases %standard-phases
+ (add-after 'unpack 'parallel-jobs
+ ;; build with multiple cores
+ (lambda _
+ (substitute* "setup.py" (("self.parallel if self.parallel else 1") (number->string (parallel-job-count)))))))))
(native-inputs
`(("cmake" ,cmake)))
(home-page "https://github.com/lief-project/LIEF")
@@ -256,7 +268,7 @@ thus should be able to compile on most platforms where these exist.")
(license license:gpl3+))) ; license is with openssl exception
(define-public python-elfesteem
- (let ((commit "87bbd79ab7e361004c98cc8601d4e5f029fd8bd5"))
+ (let ((commit "2eb1e5384ff7a220fd1afacd4a0170acff54fe56"))
(package
(name "python-elfesteem")
(version (git-version "0.1" "1" commit))
@@ -269,8 +281,7 @@ thus should be able to compile on most platforms where these exist.")
(file-name (git-file-name name commit))
(sha256
(base32
- "1nyvjisvyxyxnd0023xjf5846xd03lwawp5pfzr8vrky7wwm5maz"))
- (patches (search-our-patches "elfsteem-value-error-python-39.patch"))))
+ "07x6p8clh11z8s1n2kdxrqwqm2almgc5qpkcr9ckb6y5ivjdr5r6"))))
(build-system python-build-system)
;; There are no tests, but attempting to run python setup.py test leads to
;; PYTHONPATH problems, just disable the test
@@ -403,6 +414,11 @@ thus should be able to compile on most platforms where these exist.")
(string-append indent
"@unittest.skip(\"Disabled by Guix\")\n"
line)))
+ (substitute* "tests/test_validate.py"
+ (("^(.*)def test_revocation_mode_soft" line indent)
+ (string-append indent
+ "@unittest.skip(\"Disabled by Guix\")\n"
+ line)))
#t))
(replace 'check
(lambda _
@@ -521,6 +537,12 @@ inspecting signatures in Mach-O binaries.")
(define (make-glibc-without-werror glibc)
(package-with-extra-configure-variable glibc "enable_werror" "no"))
+(define (make-glibc-with-stack-protector glibc)
+ (package-with-extra-configure-variable glibc "--enable-stack-protector" "all"))
+
+(define (make-glibc-with-bind-now glibc)
+ (package-with-extra-configure-variable glibc "--enable-bind-now" "yes"))
+
(define-public glibc-2.24
(package
(inherit glibc-2.31)
@@ -538,7 +560,8 @@ inspecting signatures in Mach-O binaries.")
"glibc-versioned-locpath.patch"
"glibc-2.24-elfm-loadaddr-dynamic-rewrite.patch"
"glibc-2.24-no-build-time-cxx-header-run.patch"
- "glibc-2.24-fcommon.patch"))))))
+ "glibc-2.24-fcommon.patch"
+ "glibc-2.24-guix-prefix.patch"))))))
(define-public glibc-2.27/bitcoin-patched
(package
@@ -555,7 +578,8 @@ inspecting signatures in Mach-O binaries.")
"1b2n1gxv9f4fd5yy68qjbnarhf8mf4vmlxk10i3328c1w5pmp0ca"))
(patches (search-our-patches "glibc-ldd-x86_64.patch"
"glibc-2.27-riscv64-Use-__has_include-to-include-asm-syscalls.h.patch"
- "glibc-2.27-dont-redefine-nss-database.patch"))))))
+ "glibc-2.27-dont-redefine-nss-database.patch"
+ "glibc-2.27-guix-prefix.patch"))))))
(packages->manifest
(append
@@ -590,12 +614,11 @@ inspecting signatures in Mach-O binaries.")
gcc-toolchain-10
(list gcc-toolchain-10 "static")
;; Scripting
- perl
python-3
;; Git
- git
+ git-minimal
;; Tests
- lief)
+ (fix-ppc64-nx-default lief))
(let ((target (getenv "HOST")))
(cond ((string-suffix? "-mingw32" target)
;; Windows
@@ -606,8 +629,8 @@ inspecting signatures in Mach-O binaries.")
((string-contains target "-linux-")
(list (cond ((string-contains target "riscv64-")
(make-bitcoin-cross-toolchain target
- #:base-libc (make-glibc-without-werror glibc-2.27/bitcoin-patched)
- #:base-kernel-headers base-linux-kernel-headers))
+ #:base-libc (make-glibc-with-stack-protector
+ (make-glibc-with-bind-now (make-glibc-without-werror glibc-2.27/bitcoin-patched)))))
(else
(make-bitcoin-cross-toolchain target)))))
((string-contains target "darwin")
diff --git a/contrib/guix/patches/elfsteem-value-error-python-39.patch b/contrib/guix/patches/elfsteem-value-error-python-39.patch
deleted file mode 100644
index 21e1228afd..0000000000
--- a/contrib/guix/patches/elfsteem-value-error-python-39.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/examples/otool.py b/examples/otool.py
-index 2b8efc0..d797b2e 100755
---- a/examples/otool.py
-+++ b/examples/otool.py
-@@ -342,7 +342,7 @@ if __name__ == '__main__':
- try:
- e = macho_init.MACHO(raw,
- parseSymbols = False)
-- except ValueError, err:
-+ except ValueError as err:
- print("%s:" %file)
- print(" %s" % err)
- continue
diff --git a/contrib/guix/patches/gcc-10-remap-guix-store.patch b/contrib/guix/patches/gcc-10-remap-guix-store.patch
new file mode 100644
index 0000000000..a47ef7a2df
--- /dev/null
+++ b/contrib/guix/patches/gcc-10-remap-guix-store.patch
@@ -0,0 +1,25 @@
+From aad25427e74f387412e8bc9a9d7bbc6c496c792f Mon Sep 17 00:00:00 2001
+From: Andrew Chow <achow101-github@achow101.com>
+Date: Wed, 6 Jul 2022 16:49:41 -0400
+Subject: [PATCH] guix: remap guix store paths to /usr
+
+---
+ libgcc/Makefile.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
+index 851e7657d07..476c2becd1c 100644
+--- a/libgcc/Makefile.in
++++ b/libgcc/Makefile.in
+@@ -854,7 +854,7 @@ endif
+ # libgcc_eh.a, only LIB2ADDEH matters. If we do, only LIB2ADDEHSTATIC and
+ # LIB2ADDEHSHARED matter. (Usually all three are identical.)
+
+-c_flags := -fexceptions
++c_flags := -fexceptions $(shell find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;)
+
+ ifeq ($(enable_shared),yes)
+
+--
+2.37.0
+
diff --git a/contrib/guix/patches/glibc-2.24-guix-prefix.patch b/contrib/guix/patches/glibc-2.24-guix-prefix.patch
new file mode 100644
index 0000000000..875e8cd611
--- /dev/null
+++ b/contrib/guix/patches/glibc-2.24-guix-prefix.patch
@@ -0,0 +1,25 @@
+Without ffile-prefix-map, the debug symbols will contain paths for the
+guix store which will include the hashes of each package. However, the
+hash for the same package will differ when on different architectures.
+In order to be reproducible regardless of the architecture used to build
+the package, map all guix store prefixes to something fixed, e.g. /usr.
+
+We might be able to drop this in favour of using --with-nonshared-cflags
+when we being using newer versions of glibc.
+
+--- a/Makeconfig
++++ b/Makeconfig
+@@ -950,6 +950,10 @@ object-suffixes-for-libc += .oS
+ # shared objects. We don't want to use CFLAGS-os because users may, for
+ # example, make that processor-specific.
+ CFLAGS-.oS = $(CFLAGS-.o) $(PIC-ccflag)
++
++# Map Guix store paths to /usr
++CFLAGS-.oS += `find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;`
++
+ CPPFLAGS-.oS = $(CPPFLAGS-.o) -DPIC -DLIBC_NONSHARED=1
+ libtype.oS = lib%_nonshared.a
+ endif
+--
+2.35.1
+
diff --git a/contrib/guix/patches/glibc-2.27-guix-prefix.patch b/contrib/guix/patches/glibc-2.27-guix-prefix.patch
new file mode 100644
index 0000000000..d777af74f0
--- /dev/null
+++ b/contrib/guix/patches/glibc-2.27-guix-prefix.patch
@@ -0,0 +1,25 @@
+Without ffile-prefix-map, the debug symbols will contain paths for the
+guix store which will include the hashes of each package. However, the
+hash for the same package will differ when on different architectures.
+In order to be reproducible regardless of the architecture used to build
+the package, map all guix store prefixes to something fixed, e.g. /usr.
+
+We might be able to drop this in favour of using --with-nonshared-cflags
+when we being using newer versions of glibc.
+
+--- a/Makeconfig
++++ b/Makeconfig
+@@ -992,6 +992,10 @@ object-suffixes :=
+ CPPFLAGS-.o = $(pic-default)
+ # libc.a must be compiled with -fPIE/-fpie for static PIE.
+ CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
++
++# Map Guix store paths to /usr
++CFLAGS-.o += `find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;`
++
+ libtype.o := lib%.a
+ object-suffixes += .o
+ ifeq (yes,$(build-shared))
+--
+2.35.1
+
diff --git a/contrib/guix/patches/lief-fix-ppc64-nx-default.patch b/contrib/guix/patches/lief-fix-ppc64-nx-default.patch
new file mode 100644
index 0000000000..101bc1ddc0
--- /dev/null
+++ b/contrib/guix/patches/lief-fix-ppc64-nx-default.patch
@@ -0,0 +1,29 @@
+Correct default for Binary::has_nx on ppc64
+
+From the Linux kernel source:
+
+ * This is the default if a program doesn't have a PT_GNU_STACK
+ * program header entry. The PPC64 ELF ABI has a non executable stack
+ * stack by default, so in the absence of a PT_GNU_STACK program header
+ * we turn execute permission off.
+
+This patch can be dropped the next time we update LIEF.
+
+diff --git a/src/ELF/Binary.cpp b/src/ELF/Binary.cpp
+index a90be1ab..fd2d9764 100644
+--- a/src/ELF/Binary.cpp
++++ b/src/ELF/Binary.cpp
+@@ -1084,7 +1084,12 @@ bool Binary::has_nx() const {
+ return segment->type() == SEGMENT_TYPES::PT_GNU_STACK;
+ });
+ if (it_stack == std::end(segments_)) {
+- return false;
++ if (header().machine_type() == ARCH::EM_PPC64) {
++ // The PPC64 ELF ABI has a non-executable stack by default.
++ return true;
++ } else {
++ return false;
++ }
+ }
+
+ return !(*it_stack)->has(ELF_SEGMENT_FLAGS::PF_X);
diff --git a/contrib/guix/patches/nsis-disable-installer-reloc.patch b/contrib/guix/patches/nsis-disable-installer-reloc.patch
new file mode 100644
index 0000000000..4914527e56
--- /dev/null
+++ b/contrib/guix/patches/nsis-disable-installer-reloc.patch
@@ -0,0 +1,30 @@
+Patch NSIS so that it's installer stubs, produced at NSIS build time,
+do not contain .reloc sections, which will exist by default when using
+binutils/ld 2.36+.
+
+This ultimately fixes an issue when running the installer with the
+"Force randomization for images (Mandatory ASLR)" setting active.
+
+This patch has not yet been sent upstream, because it's not clear if this
+is the best fix, for the underlying issue, which seems to be that makensis
+doesn't account for .reloc sections when it builds installers.
+
+The existence of a reloc section shouldn't be a problem, and, if anything,
+is actually a requirement for working ASLR. All other Windows binaries we
+produce contain them, and function correctly when under the same
+"Force randomization for images (Mandatory ASLR)" setting.
+
+See:
+https://github.com/bitcoin/bitcoin/issues/25726
+https://sourceforge.net/p/nsis/bugs/1131/
+
+--- a/SCons/Config/gnu
++++ b/SCons/Config/gnu
+@@ -102,6 +102,7 @@ stub_env.Append(LINKFLAGS = ['-mwindows']) # build windows executables
+ stub_env.Append(LINKFLAGS = ['$NODEFLIBS_FLAG']) # no standard libraries
+ stub_env.Append(LINKFLAGS = ['$ALIGN_FLAG']) # 512 bytes align
+ stub_env.Append(LINKFLAGS = ['$MAP_FLAG']) # generate map file
++stub_env.Append(LINKFLAGS = ['-Wl,--disable-reloc-section'])
+
+ conf = FlagsConfigure(stub_env)
+ conf.CheckCompileFlag('-fno-tree-loop-distribute-patterns') # GCC 10: Don't generate msvcrt!memmove calls (bug #1248)
diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md
index 64e36f22b9..599a0bfa6c 100644
--- a/contrib/macdeploy/README.md
+++ b/contrib/macdeploy/README.md
@@ -20,7 +20,7 @@ can be extracted from
[Xcode_12.2.xip](https://download.developer.apple.com/Developer_Tools/Xcode_12.2/Xcode_12.2.xip).
Alternatively, after logging in to your account go to 'Downloads', then 'More'
-and search for [`Xcode_12.2`](https://developer.apple.com/download/all/?q=Xcode%2012.2).
+and search for [`Xcode 12.2`](https://developer.apple.com/download/all/?q=Xcode%2012.2).
An Apple ID and cookies enabled for the hostname are needed to download this.
diff --git a/contrib/message-capture/message-capture-parser.py b/contrib/message-capture/message-capture-parser.py
index eefd22a60e..33759ee713 100755
--- a/contrib/message-capture/message-capture-parser.py
+++ b/contrib/message-capture/message-capture-parser.py
@@ -79,8 +79,7 @@ def to_jsonable(obj: Any) -> Any:
val = getattr(obj, slot, None)
if slot in HASH_INTS and isinstance(val, int):
ret[slot] = ser_uint256(val).hex()
- elif slot in HASH_INT_VECTORS:
- assert all(isinstance(a, int) for a in val)
+ elif slot in HASH_INT_VECTORS and all(isinstance(a, int) for a in val):
ret[slot] = [ser_uint256(a).hex() for a in val]
else:
ret[slot] = to_jsonable(val)
diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py
index 37c6f5fd7c..eda58c370f 100755
--- a/contrib/seeds/makeseeds.py
+++ b/contrib/seeds/makeseeds.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2013-2020 The Bitcoin Core developers
+# Copyright (c) 2013-2022 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
@@ -7,10 +7,10 @@
#
import argparse
+import collections
import ipaddress
import re
import sys
-import collections
from typing import List, Dict, Union
from asmap import ASMap, net_to_prefix
@@ -38,7 +38,8 @@ PATTERN_AGENT = re.compile(
r"0.20.(0|1|2|99)|"
r"0.21.(0|1|2|99)|"
r"22.(0|99)|"
- r"23.99"
+ r"23.(0|99)|"
+ r"24.99"
r")")
def parseline(line: str) -> Union[dict, None]:
diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt
index d8e34bdb60..f8572b26c7 100644
--- a/contrib/seeds/nodes_main.txt
+++ b/contrib/seeds/nodes_main.txt
@@ -1,688 +1,856 @@
-2.37.30.144:8777
-2.138.174.158:8333
-2.152.78.124:8333
-5.8.18.154:8333
-5.45.74.50:8333
-5.79.123.3:8333
-5.102.168.217:22220
-5.103.137.146:9333
-5.128.87.126:8333
-5.172.132.200:8333
-5.188.62.18:8333
-5.254.101.226:8334
-8.210.18.56:8333
-8.210.92.32:8333
-14.13.34.225:16181
-14.39.151.167:8333
-18.196.79.108:8333
-18.218.139.58:48333
-20.184.15.116:8433
-23.175.0.220:8333
-23.233.107.21:8333
-24.35.68.229:8333
-24.37.3.26:8333
-24.102.91.203:8333
-24.116.153.115:8333
-24.134.6.165:8333
-24.155.218.13:8333
-24.160.137.173:8333
-24.177.106.85:8333
-24.184.0.146:8333
-24.194.222.116:8333
-24.205.215.192:8333
-27.124.108.19:8333
-31.14.40.64:8333
-31.47.202.112:8333
-31.165.115.7:8333
-34.65.45.157:8333
-34.78.48.104:8333
-34.80.134.68:8333
-34.101.132.198:8333
-34.227.68.216:8333
-35.137.212.22:8333
-35.231.190.134:8333
-37.1.217.35:8333
-37.15.62.32:8333
-37.143.118.174:8333
-37.200.59.67:8333
-37.205.9.165:8333
-38.23.180.228:8333
-38.65.119.26:8333
-38.141.134.140:8333
-39.109.122.127:8444
-41.79.70.146:8333
-41.193.122.191:8333
-43.225.62.107:8333
-45.35.73.152:8333
-45.43.97.103:8333
-45.63.10.52:20008
-45.84.153.40:8333
-45.95.64.225:8333
-45.129.180.214:8333
-45.154.255.162:8333
-45.226.80.102:8333
-46.6.10.230:8333
-46.23.87.218:8333
-46.32.50.98:8333
-46.47.84.85:8333
-46.48.126.58:8333
-46.146.248.89:8333
-46.165.221.209:9333
-46.166.142.2:8333
-46.166.162.45:20001
-46.173.50.58:8333
-46.175.178.3:8333
-46.188.30.118:8333
-46.219.120.59:3673
-46.229.238.187:8333
-47.93.230.171:8333
-47.100.162.210:18332
-47.144.106.249:8333
-47.188.70.205:8333
-47.227.226.242:8333
-50.2.13.164:8333
-50.5.46.195:8333
-50.45.128.28:8333
-51.148.153.60:8333
-51.154.62.103:8333
-51.154.131.18:8333
-51.158.150.155:8333
-51.159.2.218:8333
-54.198.19.34:8333
-58.105.168.41:8333
-58.158.0.86:8333
-60.251.129.61:8336
-61.239.91.250:8333
-62.28.190.194:8333
-62.152.58.16:9421
-62.171.129.32:8333
-62.251.54.163:8333
-63.247.147.166:8333
-64.33.68.176:8333
-64.156.192.61:8333
-64.187.175.226:8333
-64.233.245.39:8333
-64.237.82.149:8333
-65.101.247.26:8333
-66.29.129.218:8333
-66.49.204.11:8333
-66.58.243.215:8333
-66.85.234.129:8333
-66.130.120.52:8333
-67.10.121.145:8333
-67.210.228.203:8333
-67.213.87.21:8333
-68.181.4.12:8333
-69.7.124.146:8333
-69.8.175.201:8333
-69.59.18.22:8333
-69.119.193.9:8333
-69.130.201.27:8333
-69.131.101.176:8333
-70.15.194.32:8333
-70.64.27.12:8333
-72.29.170.151:8333
-72.74.34.99:8333
-72.133.177.119:8333
-73.166.84.222:8333
-74.67.240.204:8333
-74.91.115.229:8333
-74.118.137.119:8333
-74.213.251.203:8333
-74.220.255.190:8333
-76.11.60.155:8333
-76.66.144.127:8333
-77.70.16.245:8333
-77.85.204.149:8333
-77.105.87.97:8333
-77.120.113.69:8433
-77.120.113.71:8433
-77.120.122.116:8433
-77.120.122.118:8433
-77.162.190.90:8333
-77.167.245.239:55544
-77.232.41.189:8333
-78.20.227.249:8333
-78.21.167.8:8333
-78.27.139.13:8333
-78.43.208.25:8333
-78.63.28.146:8333
-78.72.228.239:8333
-78.108.102.8:8333
-78.129.0.39:8333
-78.129.169.69:8333
-79.77.182.180:8333
-79.77.182.183:8333
-79.107.178.59:8333
-80.55.225.158:8333
-80.64.211.102:8333
-80.64.211.103:8333
-80.71.57.50:8333
-80.81.3.27:8333
-80.82.55.43:8333
-80.88.172.227:64264
-80.89.203.172:8001
-80.93.213.246:8333
-80.147.82.165:8333
-80.229.28.60:8333
-80.247.233.40:8333
-80.255.8.93:8333
-81.7.17.202:8333
-81.10.241.165:8333
-81.21.86.157:8333
-81.171.22.143:8333
-81.237.206.224:8343
-82.69.23.195:8333
-82.96.96.40:8333
-82.116.50.101:8333
-82.136.99.122:8333
-82.149.97.25:17567
-82.154.24.209:8333
-82.165.241.50:8333
-82.197.218.253:8333
-82.202.68.231:8333
-83.137.41.10:8333
-83.208.6.211:8333
-83.217.8.31:44420
-83.220.110.48:8333
-83.222.138.85:8333
-83.243.191.199:8333
-84.22.139.57:8333
-84.27.155.17:8333
-84.75.28.247:8333
-84.112.60.16:8333
-84.211.7.56:8333
-84.237.7.249:8333
-85.23.51.177:8333
-85.24.145.198:8333
-85.184.138.108:8333
-85.194.238.134:8333
-85.195.54.110:8333
-85.208.71.36:8333
-85.208.71.39:8333
-85.214.136.45:8333
-85.214.161.252:8333
-85.227.245.128:8333
-86.18.34.243:8333
-86.20.50.170:8333
-86.49.105.90:8333
-86.76.7.132:8333
-86.100.26.188:8333
-86.106.143.143:55373
-86.120.58.66:8333
-86.133.251.239:8901
-86.149.8.23:8901
-87.78.197.234:8333
-87.120.8.5:20008
-87.121.37.156:8333
-88.82.181.44:8333
-88.87.93.52:1691
-88.98.235.134:8333
-88.136.187.214:8333
-88.147.244.250:8333
-88.148.153.148:8333
-88.212.45.166:8333
-88.212.55.138:8333
-89.38.96.153:9273
-89.47.161.135:8333
-89.88.62.190:8333
-89.158.32.44:8333
-89.163.145.240:8333
-89.163.249.234:3673
-89.176.196.80:8333
-89.216.21.96:8333
-90.84.227.255:8333
-90.146.130.214:8333
-90.250.9.1:8333
-91.93.194.154:8333
-91.106.188.229:8333
-91.126.40.109:8333
-91.137.127.123:8333
-91.147.232.98:8333
-91.152.123.18:8333
-91.178.17.120:8333
-91.204.99.178:8333
-91.223.175.14:8333
-92.42.110.242:8333
-92.53.90.84:8333
-92.221.155.228:8333
-93.57.81.162:8333
-93.95.88.13:8333
-93.103.13.1:8333
-93.123.180.164:8333
-93.190.117.26:8333
-94.105.125.240:8333
-94.110.23.215:8333
-94.154.159.99:8333
-94.189.161.119:8333
-94.203.255.70:8333
-94.232.173.93:8333
-95.79.122.99:8333
-95.80.1.110:8333
-95.83.73.31:8333
-95.110.133.223:8333
-95.110.234.93:8333
-95.164.65.194:8333
-95.165.8.182:8333
-95.174.219.101:8333
-95.191.130.100:8333
-95.214.53.154:8333
-95.215.205.180:8333
-96.43.130.234:8333
-98.25.201.31:8333
-98.128.247.182:8333
-98.171.21.129:8333
-99.147.135.161:8333
-101.100.163.118:8327
-102.132.245.16:8333
-102.182.204.96:8333
-102.182.235.245:8333
-103.14.245.250:8333
-103.47.192.15:8333
-103.84.84.250:8335
-103.99.168.130:8333
-103.99.168.140:8333
-103.198.192.14:20008
-103.232.104.227:8333
-104.143.2.195:8333
-104.172.235.227:8333
-104.238.220.199:8333
-107.11.115.68:8333
-107.173.166.43:8333
-108.4.212.83:8333
-109.136.73.97:8333
-109.173.98.23:8333
-109.190.68.116:8333
-109.235.246.60:8333
-109.248.206.13:8333
-110.12.64.96:8333
-111.90.140.46:8333
-111.90.159.184:50001
-113.107.201.131:8333
-115.47.141.250:8885
-116.58.171.67:8333
-116.87.57.218:8333
-116.202.161.56:8333
-117.51.159.130:8333
-118.103.126.140:28333
-121.45.190.210:8333
-121.99.193.25:8333
-122.112.148.153:8339
-122.148.135.234:8333
-128.0.190.26:8333
-128.65.194.136:8333
-129.126.172.115:8333
-129.226.125.10:8333
-131.188.40.191:8333
-134.195.185.52:8333
-135.180.44.61:8333
-136.52.114.123:8333
-136.56.170.96:8333
-137.116.213.143:8333
-137.226.34.46:8333
-138.43.233.57:8333
-139.130.41.82:8333
-140.190.12.129:8333
-142.4.105.77:8333
-142.54.181.218:8333
-143.177.231.247:8333
-143.178.64.10:8333
-144.34.161.65:18333
-146.4.124.134:8333
-146.83.56.69:8333
-146.90.193.68:8333
-146.196.55.156:28833
-148.66.50.50:8335
-148.251.1.20:8343
-151.48.95.212:8333
-151.252.193.245:8333
-152.44.137.83:8333
-152.115.191.196:8333
-154.221.31.86:8333
-156.17.103.2:8088
-157.138.20.22:8333
-158.58.188.37:8333
-158.140.209.79:8333
-159.89.230.128:8333
-159.246.25.52:8333
-160.20.59.250:8433
-162.0.234.190:8333
-162.62.26.218:8333
-162.250.188.194:8333
-162.251.70.82:8333
-163.158.206.255:8333
-164.68.105.105:8333
-165.228.174.117:8333
-166.62.82.103:32771
-166.70.49.26:8333
-166.78.241.9:8333
-166.78.241.25:8333
-167.71.73.244:8333
-167.179.147.155:8333
-168.91.238.8:8333
-172.105.21.216:8333
-172.117.105.95:8333
-173.23.103.30:8000
-173.205.92.151:54805
-173.205.92.154:54805
-173.205.92.157:54805
-173.208.152.218:8333
-173.241.227.243:8333
-174.3.4.232:8333
-174.17.11.22:8333
-174.88.241.167:8333
-174.114.102.41:8333
-174.114.250.86:8333
-174.142.191.136:8333
-175.39.72.87:8333
-176.12.16.135:8333
-176.37.23.30:8333
-176.62.179.221:8333
-176.74.136.237:8333
-176.99.6.226:8333
-176.212.185.153:8333
-177.81.236.117:8333
-178.19.106.26:8333
-178.21.118.178:8333
-178.33.232.69:8333
-178.79.84.139:8333
-178.124.162.209:8333
-178.132.2.246:8333
-178.150.96.46:8333
-178.162.212.44:8333
-178.193.226.120:8333
-178.236.137.63:8333
-180.150.46.187:8333
-181.164.210.228:8530
-183.110.220.210:30301
-184.95.58.166:8336
-184.164.147.82:41333
-184.171.208.109:8333
-185.17.143.220:8333
-185.21.217.49:8333
-185.25.48.184:8333
-185.28.96.16:8333
-185.31.136.246:8333
-185.64.116.15:8333
-185.68.249.91:8333
-185.108.247.190:8333
-185.141.60.36:8333
-185.148.3.227:8333
-185.148.145.74:8333
-185.159.20.143:8333
-185.167.113.59:8333
-185.185.26.141:8111
-185.189.132.178:57780
-185.204.197.112:8333
-185.209.70.17:8333
-185.220.156.193:8333
-185.238.129.113:8333
-185.239.221.5:8333
-185.244.217.39:8333
-185.254.97.164:8333
-186.33.167.11:8333
-188.32.14.31:8334
-188.42.40.234:18333
-188.134.8.36:8333
-188.138.88.14:8333
-188.156.110.239:8333
-188.165.244.143:8333
-188.213.68.38:8333
-188.214.129.65:20012
-188.242.15.74:8333
-188.244.4.78:8333
-189.39.6.82:8333
-189.207.46.32:8333
-189.212.121.74:8333
-192.3.11.20:8333
-192.65.170.15:8333
-192.146.137.44:8333
-192.182.157.119:8333
-192.187.109.141:8333
-192.227.80.83:8333
-193.10.203.23:8334
-193.32.127.160:58477
-193.32.127.162:58477
-193.58.196.212:8333
-193.106.29.106:8333
-193.138.154.43:8333
-193.178.170.232:8333
-193.196.37.62:8333
-193.222.130.14:8333
-193.234.50.227:8333
-194.14.246.205:8333
-194.135.135.69:8333
-194.147.113.201:8333
-194.165.30.20:8333
-194.219.62.23:8333
-195.56.63.4:8333
-195.134.183.188:8333
-195.208.103.30:8444
-195.208.103.31:8444
-198.1.231.6:8333
-198.12.14.136:8333
-198.84.237.70:8333
-198.178.120.5:8112
-199.48.92.184:8333
-199.68.199.19:8333
-199.182.184.204:8333
-199.189.242.141:8333
-199.247.7.208:8333
-200.122.181.37:8333
-201.191.6.103:8333
-202.107.219.130:8333
-202.108.211.135:8333
-203.94.33.112:8333
-203.130.48.117:8885
-203.132.94.196:8333
-203.162.13.181:8332
-204.191.201.43:8333
-204.229.10.90:8333
-205.178.41.124:8333
-206.55.178.157:8333
-206.126.203.8:8333
-206.174.115.96:8333
-206.223.153.52:8333
-207.188.159.25:8333
-207.229.46.80:8333
-209.58.145.157:8333
-209.126.81.147:8333
-209.145.63.150:8333
-209.209.10.30:8333
-209.237.127.227:8333
-212.99.226.36:9020
-212.185.86.84:8333
-212.227.211.87:8333
-213.5.36.58:8333
-213.89.236.219:8333
-213.93.145.183:8333
-213.214.66.182:8333
-216.41.249.178:8333
-216.146.251.8:8333
-216.249.70.22:8333
-217.11.240.4:8333
-217.15.178.7:8333
-217.24.233.116:8333
-217.64.148.98:51401
-217.113.121.169:8333
-217.170.124.170:8333
-220.132.135.54:8333
-220.221.58.25:8333
-220.233.178.199:8333
-221.219.97.105:2001
-[2001:1608:1b:f9::1]:26491
-[2001:1620:510::2]:8333
-[2001:1bc0:c1::2000]:8333
-[2001:470:1f0a:89a::2]:8333
-[2001:470:de5a::ec]:9333
-[2001:4b98:dc0:45:216:3eff:fea2:95cd]:8333
-[2001:4dd0:3564:0:fd76:c1d3:1854:5bd9]:8333
-[2001:4de8:b1b2:1:0:dead:beef:7]:8333
-[2001:638:a000:4140::ffff:191]:8333
-[2001:648:2800:131:4b1f:f6fc:20f7:f99f]:8333
-[2001:678:cc8::1:10:88]:20008
-[2001:67c:26b4:ff00::44]:8333
-[2001:67c:2db8:13::92]:8333
-[2001:7c0:2310:0:f816:3eff:fe6c:4f58]:8333
-[2001:818:ea1b:7600:f053:aade:f47b:b701]:8333
-[2001:8f1:1404:3700:8e49:715a:2e09:b634]:9444
-[2001:985:55a0:1::2]:8333
-[2001:999:270:2c2c:c8b:3a20:3f2f:318f]:8333
-[2001:b07:ac9:442b:79d6:bbbe:b37c:a783]:8333
-[2002:2f5b:a5f9::2f5b:a5f9]:8885
-[2002:b6ff:3dca::b6ff:3dca]:28364
-[2400:2410:cea2:d00:41bc:c9ea:861b:51ee]:8333
-[2400:3b00:20:c:bacb:29ff:feab:8886]:8333
-[2401:d002:3902:700:d72c:5e22:4e95:389d]:8333
-[2403:6200:88a0:fb17:f5f2:d8b5:b7ba:f4d3]:8333
-[2405:9800:b910:5f8e:1830:f630:2cc6:88fb]:8333
-[2405:9800:b970:c64c:109f:74e7:ae5f:87c7]:8333
-[2405:aa00:2::40]:8333
-[2407:8800:bc61:2202:d63d:7eff:fe6c:dc36]:8333
-[2408:8248:7004:f831::83c]:8333
-[2409:10:ca20:1df0:224:e8ff:fe1f:60d9]:8333
-[240b:11:43a1:bd00:e589:f8a7:49b:3b86]:8333
-[240d:1a:791:3400:d65d:64ff:fe28:927e]:8333
-[240d:1a:791:3400:d681:d7ff:fef6:a21e]:10050
-[2600:1700:5b2b:5f::8040]:8333
-[2600:2104:1003:c5ab:dc5e:90ff:fe18:1d08]:8333
-[2600:3c00:e002:2e32::1:14]:8333
-[2600:8805:2400:14e:12dd:b1ff:fef2:3013]:8333
-[2602:ffb8::208:72:57:200]:8333
-[2603:301f:1ebf:e000:e23f:49ff:fee7:7431]:8333
-[2603:6081:1800:6600:16dd:a9ff:feee:b2f3]:8333
-[2604:1380:1000:7400::1]:8333
-[2604:4500::2e06]:8112
-[2604:5500:c134:4000:7285:c2ff:fe4a:e143]:32797
-[2604:5500:c134:4000::3fc]:32797
-[2604:7c00:120:4b::eb24]:8333
-[2605:6400:30:f220::]:8333
-[2605:6f80:0:7:fc1b:ccff:fe8a:d822]:8333
-[2605:ae00:203::203]:8333
-[2605:c000:2a0a:1::102]:8333
-[2605:f700:c0:827:225:90ff:fee3:34a6]:8333
-[2607:9280:b:73b:250:56ff:fe14:25b5]:8333
-[2607:f2f8:ad40:bc1::1]:8333
-[2607:fa18:3a01::20]:8333
-[2620:11c:5001:1118:d267:e5ff:fee9:e673]:8333
-[2620:11c:5001:2199:d267:e5ff:fee9:e673]:8333
-[2620:6:2003:105:2d8:61ff:fe0f:853]:8333
-[2620:6e:a000:1:42:42:42:42]:8333
-[2803:cf00:af8:f200:b89e:cf34:92c7:2d26]:8333
-[2804:14c:65d1:402c:bc53:bf5d:68a:2136]:8333
-[2804:7f1:e783:d401:661c:67ff:feba:5547]:8333
-[2804:d57:5537:4800:21e:67ff:fea8:d798]:8333
-[2804:d57:5537:4800:3615:9eff:fe23:d610]:8333
-[2806:2f0:2080:62a:86f:1a01:c44f:1794]:8333
-[2a00:1028:8382:bf22:5f7f:b78f:2737:7739]:8333
-[2a00:12e0:101:99:20c:29ff:fe29:d03f]:8333
-[2a00:1328:e101:c00::163]:8333
-[2a00:1630:10:1003:0:b19:b00b:babe]:8333
-[2a00:1768:2001:27::ef6a]:8333
-[2a00:1828:a004:2::666]:8333
-[2a00:1838:2a:1400:92e2:baff:fe4a:c416]:8333
-[2a00:1c10:2:709::217]:22220
-[2a00:1f40:5001:108:5d17:7703:b0f5:4133]:8333
-[2a00:6020:15dd:ee00:c8c2:2c77:1749:35db]:8333
-[2a00:6020:b482:9200:491a:358c:d8f7:1da]:8333
-[2a00:7145:c1:1:ae29:727:2b87:f64]:5141
-[2a00:8a60:e012:a00::21]:8333
-[2a00:a040:100:f3:45a5:ac0:fea3:71e1]:8333
-[2a01:488:2000:9801::d]:8333
-[2a01:490:16:301::2]:8333
-[2a01:5200:6c:6162:7a61:746b:6f2e:736b]:8333
-[2a01:6380:fffe:73:4e3:b3cc:a871:36d1]:8333
-[2a01:7a0:2:137c::3]:8333
-[2a01:7c8:aac9:c9:5054:ff:fedf:ff95]:8333
-[2a01:7c8:d001:1c1:5054:ff:feee:3e1a]:8333
-[2a01:8740:1:ffc5::8c6a]:8333
-[2a01:cb00:d3d:7700:227:eff:fe28:c565]:8333
-[2a01:d0:0:1c::253]:8333
-[2a01:d0:bef2::12]:8333
-[2a01:e0a:9fb:b0e0:54f8:1901:6e83:62c1]:8333
-[2a01:e0a:aa7:c8c0:9679:affa:b6e5:efc7]:8333
-[2a02:13b8:f000:101::a]:8333
-[2a02:168:6328:0:2a8:2cff:fe68:e32c]:8333
-[2a02:2780:9000:70::7]:8333
-[2a02:2e02:3900:5400:a099:e1ff:feb6:d0e]:8333
-[2a02:390:9000:0:aaa1:59ff:fe43:b57b]:8333
-[2a02:58:97:7d20::60]:8333
-[2a02:6d40:305e:601:dea6:32ff:fe44:4b25]:8333
-[2a02:7a01::91:228:45:130]:8333
-[2a02:7aa0:1619::adc:8de0]:8333
-[2a02:7b40:3e4d:998d::1]:8333
-[2a02:7b40:592f:a187::1]:8333
-[2a02:8388:e5c6:d380:201:2eff:fe82:b3cc]:8333
-[2a02:9a0:102::110]:8333
-[2a02:a311:8143:8c00::4]:8353
-[2a02:af8:fab0:808:85:234:145:132]:8333
-[2a02:e00:fff0:506::1]:8444
-[2a02:e00:fff0:506::a]:8444
-[2a02:e98:20:1504::1]:8333
-[2a03:4000:47:f1::1]:8333
-[2a03:6000:870:0:46:23:87:218]:8333
-[2a03:7380:3015:524:afc5:d3bc:7c66:8f94]:8333
-[2a03:ec0:0:928:8c00:93ff:fe84:a007]:8333
-[2a03:ec0:0:928::701]:8333
-[2a04:2180:0:2::aa]:8333
-[2a04:52c0:101:29e::]:8333
-[2a04:52c0:103:c455::1]:8333
-[2a04:bc40:1dc3:8d::2:1001]:8333
-[2a05:1500:702:0:1c00:40ff:fe00:c]:8333
-[2a06:dd00:10:3:225:90ff:fe32:64cc]:8333
-[2a06:dd00:1:22:225:90ff:fe0e:bd48]:8333
-[2a07:6b47:100:464::9357:ffda]:8333
-[2a07:a880:4601:1062:b4b4:bd2a:39d4:7acf]:51401
-[2a07:abc4::1:946]:8333
-[2a07:abc4::89:234:180:194]:8333
-[2a09:2681:102::210]:8333
-[2a0a:c801:1:7::183]:8333
-[2a0b:f300:2:6::2]:8333
-[2a0c:59c0:18::a20e]:57658
-[2a0d:5600:24:a8e::a91e]:55373
-[2a0d:eb00:8005:1::13]:8333
-[2a10:4740:45:1:a013:d1ff:fe85:36e3]:8333
-[2a10:8b40:1::103]:8335
-[2c0f:f8f0:da51:0:70c3:eea9:9717:9579]:8333
+2.3.25.181:8333 # AS3215
+2.152.78.124:8333 # AS12430
+5.39.74.166:8333 # AS16276
+5.45.79.81:18332 # AS50673
+5.53.16.128:8333 # AS50923
+5.95.186.78:8333 # AS30722
+5.128.87.126:8333 # AS31200
+5.133.65.82:8333 # AS15440
+5.146.20.229:8333 # AS3209
+5.180.41.119:8333 # AS18978
+5.188.62.18:8333 # AS34665
+5.199.173.66:8333 # AS16125
+5.255.97.25:8333 # AS60404
+5.255.103.180:8333 # AS60404
+8.209.70.77:8333 # AS45102
+8.209.105.138:8333 # AS45102
+18.162.208.153:48332 # AS16509
+23.175.0.200:8333 # AS395502
+23.175.0.222:8333 # AS395502
+23.233.107.21:8333 # AS5645
+23.236.25.169:8333 # AS30029
+24.35.68.229:8333 # AS11404
+24.84.164.50:8333 # AS6327
+24.116.153.115:8333 # AS11492
+24.184.0.146:8333 # AS6128
+27.33.160.196:8333 # AS7545
+27.124.108.19:8333 # AS58511
+27.148.206.140:8333 # AS4134
+31.17.64.192:8333 # AS204028
+31.18.114.135:8333 # AS204028
+31.41.23.249:8333 # AS31287
+31.42.176.138:8333 # AS43641
+31.47.202.112:8333 # AS34385
+34.65.45.157:8333 # AS15169
+34.80.134.68:8333 # AS15169
+34.126.115.35:8333 # AS396982
+37.1.204.231:8333 # AS50673
+37.120.155.34:8333 # AS9009
+37.143.118.174:8333 # AS48926
+37.193.227.16:8333 # AS31200
+37.220.135.151:8333 # AS41206
+37.235.146.236:8333 # AS41268
+38.124.126.42:8333 # AS11550
+38.141.134.140:8333 # AS174
+38.145.151.150:8333 # AS40545
+40.115.137.28:8333 # AS8075
+41.72.154.66:8333 # AS37153
+41.79.70.146:8333 # AS37349
+42.193.55.135:8333 # AS45090
+43.225.62.107:8333 # AS63953
+45.43.97.103:8333 # AS26827
+45.85.48.58:8333 # AS208016
+45.126.26.229:8333 # AS45763
+45.134.142.40:8333 # AS60068
+45.154.252.162:8333 # AS13335
+46.13.216.169:8333 # AS6855
+46.23.87.218:8333 # AS51088
+46.40.127.164:8333 # AS43205
+46.48.126.58:8333 # AS12668
+46.59.13.35:8333 # AS8473
+46.72.238.17:8333 # AS12714
+46.128.141.184:8333 # AS16097
+46.146.248.89:8333 # AS9049
+46.165.221.209:9333 # AS28753
+46.166.142.2:8333 # AS43350
+46.175.178.3:8333 # AS28725
+47.36.144.51:8333 # AS20115
+47.180.49.158:8333 # AS5650
+49.228.131.133:2210 # AS133481
+50.2.13.164:8333 # AS62904
+50.35.71.51:8333 # AS20055
+50.53.250.162:8333 # AS20055
+51.68.36.57:8333 # AS16276
+51.138.4.135:30001 # AS8075
+51.154.62.103:8333 # AS15796
+51.158.150.155:8333 # AS12876
+54.176.63.16:8333 # AS16509
+58.158.0.86:8333 # AS2519
+59.138.115.137:8333 # AS2516
+59.167.191.60:8333 # AS4739
+60.205.205.119:8333 # AS37963
+60.234.122.245:8333 # AS9790
+60.240.210.155:8333 # AS7545
+61.239.91.250:8333 # AS9269
+62.74.143.11:8333 # AS3329
+62.138.162.12:8333 # AS20773
+62.169.74.233:8333 # AS2860
+62.171.129.32:8333 # AS51167
+62.209.198.65:8333 # AS6855
+63.247.147.166:8333 # AS30221
+64.98.76.62:8333 # AS32133
+66.29.129.218:8333 # AS22612
+66.96.235.28:8333 # AS63859
+66.130.120.52:8333 # AS5769
+66.198.209.243:8333 # AS33152
+66.208.64.128:8333 # AS10352
+66.225.231.148:8333 # AS23352
+67.55.3.200:8333 # AS33139
+67.58.232.107:8333 # AS14051
+67.211.92.2:8333 # AS11711
+67.223.119.122:8333 # AS22612
+68.48.131.251:8333 # AS7922
+68.181.4.12:8333 # AS47
+69.14.185.9:8333 # AS12083
+69.54.29.193:8333 # AS12282
+69.59.18.22:8333 # AS397444
+69.131.101.176:8333 # AS4181
+69.165.205.142:8833 # AS5645
+69.228.219.124:8333 # AS7018
+70.59.123.25:8333 # AS209
+70.62.13.150:8333 # AS7843
+70.66.248.170:8333 # AS6327
+70.112.153.229:8333 # AS7843
+70.160.240.132:8333 # AS22773
+70.190.177.204:8333 # AS22773
+71.28.189.239:8333 # AS398465
+71.234.125.198:8333 # AS1351
+72.74.123.179:8333 # AS701
+72.253.236.217:8333 # AS36149
+73.219.254.120:8333 # AS1351
+74.91.115.229:8333 # AS14586
+74.118.137.119:8333 # AS20326
+74.195.166.100:8333 # AS19108
+74.220.255.190:8333 # AS23175
+76.67.211.110:8333 # AS577
+76.169.163.14:8333 # AS20001
+77.32.121.162:8333 # AS35612
+77.53.135.74:8333 # AS45011
+77.70.16.245:8333 # AS8717
+77.85.204.149:8333 # AS8866
+77.107.38.239:8333 # AS62183
+77.120.26.102:8333 # AS25229
+77.162.190.90:8333 # AS1136
+78.20.227.249:8333 # AS6848
+78.21.167.8:8333 # AS6848
+78.27.139.13:8333 # AS6723
+78.90.91.220:8333 # AS8717
+78.108.108.25:8333 # AS8251
+78.108.108.38:8333 # AS8251
+79.77.182.183:8333 # AS13285
+79.98.159.7:11333 # AS44065
+79.189.211.201:8333 # AS5617
+80.55.225.158:8333 # AS5617
+80.83.186.35:8333 # AS33891
+80.88.172.227:64264 # AS31263
+80.209.87.103:9333 # AS31027
+80.229.28.60:8333 # AS2856
+81.7.16.182:8333 # AS35366
+81.7.17.202:8333 # AS35366
+81.19.10.2:8333 # AS24641
+81.88.221.190:8333 # AS39709
+81.171.22.143:8333 # AS60781
+81.224.44.164:8333 # AS3301
+81.224.160.81:8333 # AS3301
+82.1.68.54:8333 # AS5089
+82.21.164.47:8333 # AS5089
+82.64.116.5:8333 # AS12322
+82.66.10.11:8333 # AS12322
+82.96.96.40:8333 # AS29686
+82.116.50.101:8333 # AS30936
+82.129.68.62:8333 # AS48945
+82.136.99.122:8333 # AS8821
+82.154.24.209:8333 # AS8657
+82.197.215.125:8333 # AS25596
+83.128.132.91:8333 # AS15435
+83.137.41.10:8333 # AS31394
+83.208.6.211:8333 # AS5610
+83.208.193.242:8333 # AS5610
+83.222.138.85:8333 # AS31736
+83.240.124.68:8333 # AS31246
+83.243.191.199:8333 # AS41164
+84.9.5.211:8333 # AS5378
+84.28.57.90:8333 # AS6830
+84.38.3.249:8333 # AS196691
+84.112.60.16:8333 # AS8412
+84.215.56.119:8333 # AS41164
+84.226.243.175:8333 # AS6730
+84.245.14.73:8333 # AS25596
+84.252.157.90:18333 # AS200590
+84.255.244.61:8333 # AS34779
+85.23.24.123:8333 # AS16086
+85.52.185.29:8666 # AS12479
+85.58.120.201:8333 # AS12479
+85.93.96.18:8333 # AS29208
+85.165.8.197:8333 # AS2119
+85.173.165.66:8333 # AS12389
+85.184.143.105:8333 # AS39642
+85.191.74.103:8333 # AS39642
+85.194.238.134:8333 # AS47605
+85.195.54.110:8333 # AS35706
+85.195.196.142:8333 # AS13030
+85.208.69.11:8333 # AS25091
+85.208.69.21:8333 # AS25091
+85.208.71.36:8333 # AS42275
+85.208.71.39:8333 # AS42275
+85.214.118.71:8333 # AS6724
+85.214.161.252:8333 # AS6724
+85.216.32.73:8333 # AS51185
+85.254.98.221:8333 # AS13194
+86.58.11.152:8333 # AS3212
+86.95.8.249:8333 # AS1136
+86.100.26.188:8333 # AS39007
+86.106.143.143:55373 # AS9009
+86.124.145.184:8333 # AS8708
+86.133.251.239:8901 # AS2856
+87.79.94.221:8333 # AS8422
+87.120.8.5:20008 # AS34224
+87.125.157.220:8333 # AS12430
+88.9.76.133:8333 # AS3352
+88.90.184.68:8333 # AS2119
+88.151.101.14:5000 # AS41075
+88.151.101.253:5000 # AS41075
+88.198.92.47:8333 # AS24940
+88.208.115.70:8333 # AS29208
+88.210.15.24:8333 # AS212702
+88.212.45.166:8333 # AS42841
+89.102.206.238:8333 # AS16019
+89.103.111.34:8333 # AS16019
+89.114.143.113:8333 # AS12353
+89.134.62.74:8333 # AS21334
+89.152.8.231:8333 # AS2860
+89.161.26.78:8333 # AS39375
+89.207.131.19:8333 # AS49544
+89.248.193.229:8333 # AS49505
+90.3.48.62:8333 # AS3215
+90.146.121.97:8333 # AS12605
+90.146.130.214:8333 # AS12605
+90.196.169.58:8333 # AS5607
+90.250.9.1:8333 # AS5378
+91.93.194.154:8333 # AS34984
+91.126.40.109:8333 # AS35699
+91.204.99.178:8333 # AS20485
+91.204.149.5:8333 # AS42765
+91.206.17.195:8333 # AS13259
+91.209.51.131:8333 # AS48239
+91.215.91.254:8333 # AS48078
+92.91.27.60:8333 # AS15557
+92.221.20.232:8333 # AS29695
+92.255.85.31:8333 # AS9002
+93.4.101.37:8333 # AS15557
+93.46.81.5:8333 # AS12874
+93.57.81.162:8333 # AS12874
+93.73.39.196:8333 # AS25229
+93.90.82.226:8333 # AS47626
+93.95.88.13:8333 # AS35434
+93.123.180.164:8333 # AS35539
+93.189.145.169:8333 # AS12555
+94.17.185.107:8333 # AS12709
+94.75.198.120:8333 # AS60781
+94.114.196.169:8333 # AS3209
+94.142.213.250:55544 # AS5524
+94.154.159.99:8333 # AS62240
+94.158.246.183:8333 # AS39798
+94.239.145.32:8333 # AS5410
+95.31.12.22:8333 # AS8402
+95.31.196.15:8333 # AS3216
+95.110.133.223:8333 # AS31034
+95.110.234.93:8333 # AS31034
+95.161.12.45:8333 # AS39598
+95.191.130.100:8333 # AS12389
+95.208.158.161:8333 # AS51185
+95.213.145.218:8333 # AS49505
+95.214.53.154:8333 # AS201814
+95.214.53.160:8333 # AS201814
+96.44.156.199:8333 # AS8100
+97.75.145.12:8333 # AS22709
+102.132.192.141:8333 # AS37680
+103.14.245.250:8333 # AS24482
+103.85.38.205:8333 # AS134090
+103.88.92.78:8332 # AS17547
+103.99.168.100:8333 # AS6939
+103.99.168.140:8333 # AS6939
+103.99.170.210:8333 # AS54415
+103.99.170.220:8333 # AS54415
+103.100.44.70:8333 # AS10143
+103.178.236.27:8333 # AS49981
+103.209.12.144:8333 # AS58511
+104.59.147.15:8333 # AS7018
+104.129.171.121:8333 # AS174
+104.200.65.234:8333 # AS23033
+104.238.220.199:8333 # AS23470
+104.244.73.6:8333 # AS53667
+106.71.119.230:8333 # AS4804
+107.173.166.43:8333 # AS23352
+108.161.22.78:8333 # AS54154
+108.174.63.234:8333 # AS36352
+109.99.63.159:8333 # AS9050
+109.105.40.247:8333 # AS12570
+109.107.185.130:8333 # AS48282
+109.110.239.4:8333 # AS35432
+109.173.41.43:8333 # AS42610
+109.236.90.117:8333 # AS49981
+109.248.206.13:8333 # AS203493
+109.255.106.206:8333 # AS6830
+111.90.140.23:8333 # AS45839
+111.90.140.46:8333 # AS45839
+111.90.159.246:8333 # AS34309
+112.118.188.50:8333 # AS4760
+115.47.141.250:8885 # AS4134
+116.58.171.67:8333 # AS2514
+118.92.107.108:8333 # AS9500
+119.42.55.203:8333 # AS133159
+120.79.71.72:8333 # AS37963
+121.99.240.87:8333 # AS9790
+123.60.213.192:8333 # AS55990
+124.156.158.100:8333 # AS132203
+124.222.123.238:8333 # AS45090
+125.178.6.116:8333 # AS3786
+128.0.190.26:8333 # AS30764
+128.65.194.136:8333 # AS29222
+129.13.189.212:8333 # AS34878
+129.126.172.115:8333 # AS17547
+129.146.52.174:8333 # AS31898
+130.44.168.202:8333 # AS6079
+131.161.80.166:8333 # AS263694
+131.188.40.191:8333 # AS680
+134.195.185.52:8333 # AS13536
+135.134.238.47:8333 # AS4181
+135.180.218.58:8333 # AS46375
+135.181.215.237:8333 # AS24940
+136.29.109.180:8333 # AS19165
+136.32.238.6:8333 # AS16591
+136.56.170.96:8333 # AS16591
+137.25.38.108:8333 # AS20115
+137.226.34.46:8333 # AS680
+138.207.211.106:8333 # AS11776
+139.130.41.82:8333 # AS1221
+139.153.255.107:8333 # AS786
+140.190.12.129:8333 # AS14828
+142.54.181.218:8333 # AS32097
+143.177.229.149:8333 # AS50266
+143.178.64.10:8333 # AS50266
+144.24.245.183:8333 # AS31898
+144.126.130.178:8333 # AS40021
+146.4.124.129:8333 # AS3303
+146.71.69.103:8333 # AS7782
+146.83.56.69:8333 # AS23140
+147.194.177.165:8333 # AS15128
+149.90.214.78:8333 # AS12353
+149.102.157.156:8333 # AS13768
+151.248.156.55:8333 # AS8821
+151.252.193.245:8333 # AS29582
+153.92.93.114:8333 # AS41998
+154.211.6.2:8333 # AS140224
+156.17.103.2:8088 # AS8970
+156.146.177.221:8333 # AS1448
+157.131.143.173:8333 # AS46375
+158.58.188.37:8333 # AS57497
+158.248.39.239:8333 # AS29695
+159.89.230.128:8333 # AS14061
+159.196.3.239:8333 # AS4764
+159.224.189.250:8333 # AS13188
+160.72.51.154:8333 # AS46887
+161.29.236.55:8333 # AS4826
+161.97.119.166:8333 # AS51167
+161.246.11.230:8333 # AS9486
+162.62.18.226:8333 # AS132203
+162.250.123.179:8333 # AS19318
+162.250.191.222:8333 # AS26832
+162.254.118.20:8333 # AS6130
+163.172.81.70:8333 # AS12876
+164.90.47.8:8333 # AS53449
+165.228.174.117:8333 # AS1221
+166.70.145.151:8333 # AS6315
+168.91.238.8:8333 # AS11039
+170.253.11.25:8333 # AS15704
+171.103.170.115:8333 # AS7470
+172.93.166.135:8333 # AS22653
+172.103.217.236:8333 # AS25668
+172.105.21.216:8333 # AS63949
+172.112.153.95:8333 # AS20001
+173.3.218.91:8333 # AS6128
+173.12.119.133:8333 # AS7922
+173.34.127.181:8333 # AS812
+173.76.123.173:8333 # AS701
+173.176.198.68:8333 # AS5769
+173.208.152.218:8333 # AS32097
+173.241.227.243:8333 # AS19009
+173.246.27.7:8333 # AS1403
+173.255.240.205:8333 # AS63949
+174.30.47.15:8333 # AS209
+174.114.250.86:8333 # AS812
+174.138.35.229:8333 # AS14061
+174.142.191.136:8333 # AS32613
+176.10.143.190:8333 # AS8473
+176.74.136.237:8333 # AS35613
+176.118.220.29:8333 # AS60042
+176.126.116.7:8333 # AS20473
+176.126.167.10:8333 # AS8449
+176.212.185.153:8333 # AS9049
+176.235.209.186:8333 # AS34984
+177.81.236.117:8333 # AS28573
+177.89.205.70:8333 # AS28220
+178.48.168.12:8333 # AS21334
+178.124.162.209:8333 # AS6697
+178.159.98.133:8333 # AS202390
+178.196.89.209:8333 # AS3303
+178.236.137.63:8333 # AS44843
+178.252.123.24:8333 # AS42893
+179.43.170.186:8333 # AS51852
+180.150.46.187:8333 # AS4764
+181.117.128.140:8333 # AS19037
+184.19.19.16:8333 # AS5650
+185.21.217.48:8333 # AS200052
+185.25.48.184:8333 # AS61272
+185.31.136.246:8333 # AS47605
+185.52.93.45:8333 # AS39449
+185.64.116.15:8333 # AS31736
+185.68.249.91:8333 # AS51184
+185.98.54.20:8333 # AS39572
+185.107.83.55:8333 # AS43350
+185.140.253.169:8333 # AS200735
+185.148.145.74:8333 # AS44901
+185.165.170.19:8333 # AS3223
+185.167.113.59:8333 # AS207054
+185.185.26.141:8111 # AS201206
+185.197.163.136:8333 # AS60144
+185.209.12.76:8333 # AS212323
+185.209.70.17:8333 # AS204568
+185.227.156.226:8333 # AS209846
+185.233.189.210:8333 # AS61303
+185.239.221.5:8333 # AS61282
+185.244.100.106:8333 # AS2586
+185.254.97.164:8333 # AS44486
+186.33.167.11:8333 # AS1299
+186.176.98.37:8333 # AS262197
+186.249.217.25:8333 # AS7195
+186.250.95.132:8333 # AS262967
+188.32.14.31:8334 # AS42610
+188.35.167.14:8333 # AS34123
+188.68.45.143:8333 # AS47147
+188.117.200.212:8333 # AS25447
+188.138.88.14:8333 # AS20773
+188.151.237.158:8333 # AS1257
+188.154.236.49:8333 # AS6730
+189.123.177.128:8333 # AS4230
+190.123.27.11:8333 # AS52468
+190.145.127.254:8333 # AS14080
+192.69.53.77:8333 # AS11142
+192.146.137.44:8333 # AS25376
+192.222.24.54:8333 # AS22646
+192.222.147.141:8333 # AS1403
+193.32.127.162:60969 # AS39351
+193.111.198.187:8111 # AS24961
+193.196.37.62:8333 # AS34878
+194.13.80.185:15430 # AS47147
+194.147.113.201:8333 # AS21232
+194.165.30.20:8333 # AS35162
+194.191.239.98:8333 # AS1836
+195.56.63.4:8333 # AS5483
+195.56.63.10:8333 # AS5483
+195.123.239.185:8333 # AS64010
+195.140.226.154:8333 # AS35614
+198.1.231.6:8333 # AS30236
+198.148.112.27:8333 # AS35916
+199.126.234.237:8333 # AS395570
+199.193.174.173:8333 # AS7992
+199.247.7.208:8333 # AS20473
+200.122.181.46:8333 # AS3790
+201.191.6.103:8333 # AS11830
+201.212.36.209:8333 # AS7303
+201.221.234.200:8333 # AS27928
+202.108.211.135:8333 # AS4837
+202.169.17.178:8333 # AS137549
+202.177.24.140:8333 # AS7479
+203.130.48.117:8885 # AS54994
+203.132.94.196:8333 # AS38195
+205.178.41.124:8333 # AS11039
+206.72.201.228:8333 # AS19318
+206.192.203.0:8333 # AS7029
+206.223.153.52:8333 # AS19214
+207.134.216.145:8334 # AS395570
+207.188.154.50:8333 # AS15704
+207.229.46.80:8333 # AS852
+207.255.193.47:8333 # AS11776
+208.104.92.74:8333 # AS14615
+209.58.145.157:8333 # AS394380
+209.58.158.232:8335 # AS394380
+209.141.43.243:8333 # AS53667
+209.226.142.62:8333 # AS577
+209.237.127.227:8333 # AS1299
+209.237.133.54:8333 # AS53859
+211.248.90.50:8333 # AS4766
+212.21.18.78:8333 # AS20485
+212.34.225.118:8333 # AS44395
+212.51.146.137:8333 # AS13030
+212.227.211.87:8333 # AS8560
+213.0.69.76:8333 # AS3352
+213.5.36.58:8333 # AS49974
+213.47.64.105:8333 # AS8412
+213.89.135.151:8333 # AS1257
+213.141.154.201:8333 # AS12714
+213.159.198.45:8333 # AS8359
+213.184.244.24:8333 # AS60280
+213.214.66.182:8333 # AS43205
+213.226.123.76:8333 # AS49943
+216.146.251.8:8333 # AS54579
+216.186.238.14:8333 # AS12083
+217.5.150.114:8333 # AS3320
+217.15.178.11:8333 # AS25534
+217.24.239.109:8333 # AS9063
+217.64.47.138:8333 # AS39324
+217.73.80.104:8333 # AS44291
+217.79.181.38:8333 # AS24961
+217.92.55.246:8333 # AS3320
+217.113.121.169:8333 # AS8416
+217.115.116.250:8333 # AS30900
+217.155.244.170:8333 # AS13037
+217.170.124.170:8333 # AS35401
+220.132.135.54:8333 # AS3462
+220.233.178.199:8333 # AS38195
+222.154.111.46:8333 # AS4648
+[2001:1620:510::2]:8333 # AS13030
+[2001:19f0:6001:39aa:5400:3ff:fef0:916]:8333 # AS20473
+[2001:19f0:8001:f71:5400:4ff:fe10:6a63]:8333 # AS20473
+[2001:1bc0:c1::2000]:8333 # AS29686
+[2001:1c02:11e:3500:df25:6321:8260:d9be]:8333 # AS6830
+[2001:41d0:1004:1b79::]:8339 # AS16276
+[2001:41d0:203:3739::]:8333 # AS16276
+[2001:41d0:203:aacc::]:8333 # AS16276
+[2001:41d0:203:bb0a::]:8333 # AS16276
+[2001:41d0:2:bf8f::]:8333 # AS16276
+[2001:41d0:303:6586::]:8333 # AS16276
+[2001:41d0:602:4493::]:8333 # AS16276
+[2001:41d0:8:b9d8::1]:8333 # AS16276
+[2001:41d0:a:69a2::1]:8333 # AS16276
+[2001:41f0::62:6974:636f:696e]:8333 # AS6830
+[2001:44b8:256:5d11:216:3eff:fe39:d5d4]:8333 # AS4739
+[2001:470:1b62::]:8333 # AS6939
+[2001:470:1f07:803:20c:29ff:fe2d:5879]:8333 # AS6939
+[2001:470:1f15:106:e2d5:5eff:fe42:7ae5]:8333 # AS6939
+[2001:470:1f15:c43::11]:8333 # AS6939
+[2001:470:26:472::b7c]:8333 # AS6939
+[2001:470:75e9:1::10]:8333 # AS6939
+[2001:470:de5a::ec]:9333 # AS6939
+[2001:4ba0:babe:584::1]:8333 # AS24961
+[2001:4ba0:ffff:24::1]:8333 # AS24961
+[2001:4dd0:3564:0:30b7:1d7b:6fec:4c5c]:8333 # AS8422
+[2001:4dd0:3564:0:88e:b4ff:2ad0:699b]:8333 # AS8422
+[2001:4dd0:3564:0:9c1c:cc31:9fe8:5505]:8333 # AS8422
+[2001:4dd0:3564:0:a0c4:d41f:4c4:1bb0]:8333 # AS8422
+[2001:4dd0:3564:0:fd76:c1d3:1854:5bd9]:8333 # AS8422
+[2001:4dd0:3564:1::7676:8090]:8333 # AS8422
+[2001:4dd0:3564:1:b977:bd71:4612:8e40]:8333 # AS8422
+[2001:4dd0:af0e:3564::69:1]:8333 # AS8422
+[2001:4dd0:af0e:3564::69:90]:8333 # AS8422
+[2001:4de8:b1b2:1:0:dead:beef:7]:8333 # AS29208
+[2001:638:a000:4140::ffff:191]:8333 # AS680
+[2001:678:acc:42::]:8333 # AS60404
+[2001:67c:26b4:ff00::44]:8333 # AS25376
+[2001:67c:2db8:6::36]:8333 # AS39798
+[2001:7c0:2310:0:f816:3eff:fe0d:4ab6]:8333 # AS34878
+[2001:7c0:2310:0:f816:3eff:fe6c:4f58]:8333 # AS34878
+[2001:861:3246:a10::40]:8333 # AS5410
+[2001:b07:2e6:38d7:ba27:ebff:fe60:3dc1]:8333 # AS12874
+[2001:b07:6461:7811:489:d2da:e07:1af7]:8333 # AS12874
+[2001:b07:ac9:442b:79d6:bbbe:b37c:a783]:8333 # AS12874
+[2001:bc8:1600:0:208:a2ff:fe0c:8a2e]:8333 # AS12876
+[2001:bc8:323c:ff:a634:384f:1849:f4bc]:8333 # AS12876
+[2001:bc8:323c:ff:d217:c2ff:fe07:2cd9]:8333 # AS12876
+[2001:bc8:3bec:100::1]:8333 # AS12876
+[2002:2f5b:a5f9::2f5b:a5f9]:8885 # AS6939
+[2003:cb:8713:6102:aaa1:59ff:fe57:7779]:8333 # AS3320
+[2003:e0:370e:1400::5]:8333 # AS3320
+[2003:f6:3f10:6700:4c9f:7620:8324:d4a7]:8333 # AS3320
+[2400:2410:cea2:d00:41bc:c9ea:861b:51ee]:8333 # AS17676
+[2400:2411:a3e1:4900:2568:684b:e99:7120]:8333 # AS17676
+[2400:2411:a3e1:4900:2987:b88f:61e0:84fa]:8333 # AS17676
+[2400:3b00:20:c:bacb:29ff:feab:8886]:8333 # AS18229
+[2401:b140:1::100:210]:8333 # AS54415
+[2401:b140:1::100:220]:8333 # AS54415
+[2401:b140::42:100]:8333 # AS6939
+[2401:b140::44:130]:8333 # AS6939
+[2401:d002:3902:700:d72c:5e22:4e95:389d]:8333 # AS38195
+[2404:4408:6752:c000::1999]:8333 # AS9790
+[2404:7a85:4161:2b00:49a1:427a:fac:3409]:8333 # AS2518
+[2405:9800:b972:ab58:c05:e938:267e:271]:8333 # AS45430
+[2406:da11:169:b03:32b5:f901:9f7c:3e4b]:8333 # AS16509
+[2406:da14:335:b601:ceb7:b4fc:a855:f3a5]:8333 # AS16509
+[2406:da1e:a4e:8a03:2aad:496b:768d:e497]:8333 # AS16509
+[2407:8800:bc61:2202:a0c6:107:502b:4e3b]:8333 # AS7545
+[2409:10:ca20:1df0:224:e8ff:fe1f:60d9]:8333 # AS55391
+[2600:1700:22f1:641f:e8:39c8:eb1d:a1eb]:8333 # AS7018
+[2600:1700:9c5d:ed0::38]:8333 # AS7018
+[2600:1700:9c5d:ed0:d0d6:1d9:5cc2:ab47]:8333 # AS7018
+[2600:1702:1ce0:4010::40]:8333 # AS7018
+[2600:1f14:40e:e301:d155:aa3a:77be:960e]:8333 # AS16509
+[2600:1f16:a08:b901:1afa:ef4e:4ce7:2ba4]:8333 # AS16509
+[2600:1f1c:2d3:2403:5bac:3fc6:6513:7a63]:8333 # AS16509
+[2600:2104:1003:c5ab:dc5e:90ff:fe18:1d08]:8333 # AS11404
+[2600:3c00::f03c:92ff:fe92:2745]:8333 # AS63949
+[2600:3c00::f03c:92ff:fecf:61b6]:8333 # AS63949
+[2600:3c00::f03c:93ff:feb3:1b6]:8333 # AS63949
+[2600:3c00:e002:2e32::1:14]:8333 # AS63949
+[2600:3c02::f03c:92ff:fe5d:9fb]:8333 # AS63949
+[2600:4040:2854:5e00:c6e9:84ff:fe46:ee8]:8666 # AS13786
+[2600:6c54:7100:1ad1:bddf:550e:91be:f9e1]:8333 # AS20115
+[2600:8805:2400:14e:12dd:b1ff:fef2:3013]:8333 # AS22773
+[2601:184:300:bde:3c29:8e94:1ba8:fde3]:8333 # AS7922
+[2601:18c:8080:300f:219:d1ff:fe75:dc2f]:8333 # AS7922
+[2601:18d:4600:43f1:20e7:b3ff:fecf:a99]:8333 # AS7922
+[2601:18d:8701:c290::3330]:8333 # AS7922
+[2601:246:4d7f:9e28:f321:36ca:7a71:c687]:8333 # AS7922
+[2601:640:c201:960d:86eb:f27d:66a2:f2c1]:8333 # AS7922
+[2602:241:75d1:2b90::7840]:8333 # AS46375
+[2602:ffb8::208:72:57:200]:8333 # AS2914
+[2603:3004:6a1:3800:851f:584d:7aba:affb]:8333 # AS7922
+[2603:3004:6a1:3800::4402]:8333 # AS7922
+[2603:3004:70d:1400:8532:2900:ce6f:acdf]:8333 # AS7922
+[2603:3004:745:900:f0d7:556a:a8c:ced5]:8333 # AS7922
+[2603:6080:c000:5d8a::104f]:8333 # AS7843
+[2603:8000:d100:8991:cc29:ccff:fe42:300c]:8333 # AS7843
+[2603:8080:1f07:6fdd:7de2:d969:78c9:b7ea]:8333 # AS7843
+[2603:8080:7300:531::13ea]:8333 # AS7843
+[2603:80a0:703:40f8::38]:8333 # AS7843
+[2604:180:f3::218]:8333 # AS3842
+[2604:3d08:0:5:d941:4b03:a093:131b]:8333 # AS6327
+[2604:7c00:120:4b::eb24]:8333 # AS174
+[2604:a00:21:3043:bf6a:535e:dfeb:5b7b]:8333 # AS19318
+[2604:a880:400:d0::1ce7:4001]:8333 # AS14061
+[2604:a880:400:d0::1d44:e001]:8333 # AS14061
+[2604:a880:400:d0::261f:6001]:8333 # AS14061
+[2604:a880:400:d1::7e2:e001]:8333 # AS14061
+[2604:a880:4:1d0::14:3000]:8333 # AS14061
+[2604:a880:4:1d0::e5:b000]:8333 # AS14061
+[2605:6400:30:f220::]:8333 # AS53667
+[2605:6f80:0:7:fc1b:ccff:fe8a:d822]:8333 # AS53340
+[2605:a140:2076:8253::1]:8333 # AS40021
+[2605:a140:3007:1287::1]:8333 # AS40021
+[2605:ae00:203::203]:8333 # AS7819
+[2605:c000:2a0a:1::102]:8333 # AS7393
+[2607:1a00:1:d::11:7c4d]:8333 # AS22653
+[2607:5300:203:1214::]:8333 # AS16276
+[2607:9280:b:73b:250:56ff:fe14:25b5]:8333 # AS395502
+[2607:9280:b:73b:250:56ff:fe21:9c2f]:8333 # AS395502
+[2607:9280:b:73b:250:56ff:fe21:bf32]:8333 # AS395502
+[2607:9280:b:73b:250:56ff:fe33:4d1b]:8333 # AS395502
+[2607:9280:b:73b:250:56ff:fe3d:401]:8333 # AS395502
+[2607:f2c0:e1c2:69:12c3:7bff:fe4d:9431]:8333 # AS5645
+[2607:f2c0:e1c2:69:ecb2:6e88:9f33:5057]:8333 # AS5645
+[2620:6:2003:105:2d8:61ff:fe0f:853]:8333 # AS25682
+[2620:6e:a000:1:42:42:42:42]:8333 # AS397444
+[2620:a6:2000:1::3:d570]:8333 # AS27566
+[2620:a6:2000:1::5:162a]:8333 # AS27566
+[2620:a6:2000:1::5:1631]:8333 # AS27566
+[2620:a6:2000:1::c:e634]:8333 # AS27566
+[2800:40:33:8ab:a0e7:b215:fc83:5c31]:8333 # AS16814
+[2800:bf0:149:f4b:f8df:8d7d:801b:e25e]:8333 # AS27947
+[2804:14c:198:80d5:7603:41d1:d3fc:e797]:8333 # AS28573
+[2804:14d:ae81:827b:99a8:1e3f:6db2:29db]:8333 # AS4230
+[2804:d57:5537:4800:3e7c:3fff:fe7b:80aa]:8333 # AS8167
+[2a00:12e0:101:99:20c:29ff:fe29:d03f]:8333 # AS6798
+[2a00:1328:e101:c00::163]:8333 # AS31078
+[2a00:1398:4:2a03:215:5dff:fed6:1033]:8333 # AS34878
+[2a00:1398:4:2a03::bc03]:8333 # AS34878
+[2a00:1630:10:1003:0:b19:b00b:babe]:8333 # AS49544
+[2a00:1768:2001:27::ef6a]:8333 # AS43350
+[2a00:1828:a004:2::666]:8333 # AS34240
+[2a00:1c10:2:709::217]:22220 # AS50300
+[2a00:1f40:5001:108:5d17:7703:b0f5:4133]:8333 # AS42864
+[2a00:23c5:fe80:7301:d6ae:52ff:fed5:56a5]:8333 # AS2856
+[2a00:23c6:5c91:5808:c05a:4dff:fe65:9d69]:8333 # AS2856
+[2a00:6020:1bfa:d400:20c:29ff:fe61:4a4c]:8333 # AS60294
+[2a00:6020:b482:9200:491a:358c:d8f7:1da]:8333 # AS60294
+[2a00:6020:b489:2000:5054:ff:fefc:5ed8]:8333 # AS60294
+[2a00:7c80:0:25::e37a]:8333 # AS49981
+[2a00:7c80:0:71::8]:8333 # AS49981
+[2a00:8a60:e012:a00::21]:8333 # AS680
+[2a00:ae40:240e:3200::3]:8333 # AS50923
+[2a00:bbe0:cc:0:62a4:4cff:fe23:7510]:8333 # AS47605
+[2a00:ca8:a1f:3025:f949:e442:c940:13e8]:8333 # AS30764
+[2a00:d4e0:2:d002:4467:31e0:6fa5:b3ef]:8333 # AS15600
+[2a00:ee2:1200:1900:8d3:d2ff:feb1:bc58]:8333 # AS5603
+[2a01:238:420f:9200:fa5a:1a4b:1e6a:fadf]:8333 # AS6724
+[2a01:238:4389:c400:3b26:d94e:38d5:44ef]:8333 # AS6724
+[2a01:490:16:301::2]:8333 # AS8251
+[2a01:4b00:807c:3100:cda1:c6a:2bad:2418]:8333 # AS56478
+[2a01:4f8:141:2254::2]:8333 # AS24940
+[2a01:4f8:173:230a::2]:8333 # AS24940
+[2a01:4f8:190:91c4::2]:8333 # AS24940
+[2a01:4f8:200:7222::2]:8333 # AS24940
+[2a01:4f8:202:3e6::2]:8333 # AS24940
+[2a01:4f8:221:44d7::2]:8333 # AS24940
+[2a01:4f8:231:915::2]:8333 # AS24940
+[2a01:4f9:2a:1ce0::2]:8333 # AS24940
+[2a01:4f9:2b:29a::2]:8333 # AS24940
+[2a01:4f9:4a:31de::2]:8333 # AS24940
+[2a01:5200:6c:6162:7a61:746b:6f2e:736b]:8333 # AS6855
+[2a01:6380:fffe:73:10fb:d012:8581:b4d7]:8333 # AS25540
+[2a01:7a7:2:2804:ae1f:6bff:fe9d:6c94]:8333 # AS20773
+[2a01:7c8:aaac:89:5054:ff:feb7:f5cb]:8333 # AS20857
+[2a01:7c8:aac9:c9:5054:ff:fedf:ff95]:8333 # AS20857
+[2a01:7c8:d001:1c1:5054:ff:feee:3e1a]:8333 # AS20857
+[2a01:7c8:d009:2aa:5054:ff:fe1b:a196]:11520 # AS20857
+[2a01:7c8:fffa:50e:ddfe:c924:ca0a:cbab]:8333 # AS20857
+[2a01:7e00::f03c:93ff:fe59:66dc]:8333 # AS63949
+[2a01:7e01::f03c:93ff:fe3b:bb5b]:8333 # AS63949
+[2a01:8740:1:ffc5::8c6a]:8333 # AS57344
+[2a01:9f40:a000::100]:8333 # AS42908
+[2a01:cb00:d3d:7700:227:eff:fe28:c565]:8333 # AS3215
+[2a01:e0a:20:7350:919c:b1c3:8b83:adf9]:8333 # AS12322
+[2a01:e0a:301:7010:b87d:e14b:cea9:b998]:8333 # AS12322
+[2a01:e0a:48b:2d10:94f2:4d5c:ca5f:bf49]:8333 # AS12322
+[2a01:e0a:530:a0a0:f465:af5:be1b:9075]:8333 # AS12322
+[2a01:e0a:aa7:c8c0:9679:affa:b6e5:efc7]:8333 # AS12322
+[2a01:e11:100c:70:cbc8:9e31:4b77:1626]:8333 # AS12322
+[2a01:e34:ee78:3060:230:48ff:fe81:f1c6]:8333 # AS12322
+[2a02:1210:14a9:6700:a00:27ff:fe4e:82b6]:8333 # AS3303
+[2a02:1210:4639:f00:10a7:e965:509a:7a4a]:8333 # AS3303
+[2a02:1210:7c92:5100:211:32ff:feae:152d]:8333 # AS3303
+[2a02:1210:86bf:f100:3178:d700:d44d:6bb1]:8333 # AS3303
+[2a02:1210:9487:a200:edc1:93a4:945:9a92]:8333 # AS3303
+[2a02:168:420b:a::20]:8333 # AS13030
+[2a02:168:6328:0:4a21:bff:fe26:38c3]:8333 # AS13030
+[2a02:168:676e:0:e65f:1ff:fe09:3591]:8333 # AS13030
+[2a02:1748:f39f:5872:dead:beef:b1ac:c0fe]:8333 # AS51184
+[2a02:180:1:1::517:10b6]:8333 # AS35366
+[2a02:2168:a379:d100:96de:80ff:fea3:fd00]:8333 # AS42610
+[2a02:2780:9000:70::7]:8333 # AS35434
+[2a02:2780:9000:70::f]:8333 # AS35434
+[2a02:2780::e01a]:8333 # AS35434
+[2a02:2e02:3900:5400:a099:e1ff:feb6:d0e]:8333 # AS12479
+[2a02:2f05:660e:8b00::1]:8333 # AS48571
+[2a02:58:97:7d20::60]:8333 # AS25596
+[2a02:6d40:3073:c01:dea6:32ff:fe44:4b25]:8333 # AS42652
+[2a02:7a01::91:228:45:130]:8333 # AS16019
+[2a02:7b40:5928:89::1]:8333 # AS62282
+[2a02:7b40:c3b5:f583::1]:8333 # AS62282
+[2a02:8308:8087:aa00:9ea8:1b2:ef98:56bf]:8333 # AS16019
+[2a02:842a:1df:8a01:1e1b:dff:fe0b:236d]:8333 # AS15557
+[2a02:a44d:14d6:1:2c0:8ff:fe8f:b3b2]:8333 # AS1136
+[2a02:a45a:94cd:f00d::1]:8333 # AS1136
+[2a02:a45f:3b9d:30::3]:8333 # AS1136
+[2a02:a467:7833:1:7285:c2ff:fe2c:21e9]:8333 # AS1136
+[2a02:aa14:2380:b300:4040:be88:8b01:d38]:8333 # AS6830
+[2a02:c206:2044:9826::1]:8333 # AS51167
+[2a02:c206:2082:1246::1]:8333 # AS51167
+[2a02:c206:3008:2368::1]:8333 # AS51167
+[2a02:c207:0:4971::1]:5332 # AS51167
+[2a02:c207:2014:4199::1]:8333 # AS51167
+[2a02:c207:2024:6115::1]:8333 # AS51167
+[2a02:c207:2026:6682::1]:8333 # AS51167
+[2a02:c207:3002:7468::1]:8333 # AS51167
+[2a02:e98:20:1504::1]:8333 # AS24641
+[2a03:4000:6:416c::43]:8333 # AS47147
+[2a03:4000:6:f814:548b:17ff:fe31:b64a]:8333 # AS47147
+[2a03:6000:870:0:46:23:87:218]:8333 # AS51088
+[2a03:94e0:ffff:185:243:218:0:19]:8333 # AS56655
+[2a03:b0c0:1:e0::397:6001]:8333 # AS14061
+[2a03:b0c0:2:f0::163:3001]:8333 # AS14061
+[2a03:b0c0:2:f0::18a:d001]:8333 # AS14061
+[2a03:b0c0:3:d0::f3e:2001]:8333 # AS14061
+[2a03:e2c0:1347::2]:8333 # AS50113
+[2a03:ec0:0:928::701:701]:8333 # AS199669
+[2a04:52c0:103:c455::1]:8334 # AS60404
+[2a04:52c0:3007:200::2000]:8333 # AS60404
+[2a04:bc40:1dc3:8d::2:1001]:8333 # AS35277
+[2a05:1500:702:0:1c00:40ff:fe00:c]:8333 # AS48635
+[2a05:3580:d101:3700::]:8333 # AS20764
+[2a05:3580:db0b:1600:c489:76ed:313d:b33]:8333 # AS20764
+[2a05:d014:a55:4001:8127:afa7:daf9:d91b]:8333 # AS16509
+[2a05:d014:a55:4001:f6ab:dd5e:4039:b46c]:8333 # AS16509
+[2a05:d014:a55:4003:6523:50a1:152:e88c]:8333 # AS16509
+[2a05:d01a:b7b:3c01:8bf7:ae14:afb3:33ae]:8333 # AS16509
+[2a05:f480:1800:697:5400:2ff:feb6:c36d]:8333 # AS20473
+[2a06:e040:7603:2918:c6ef:464e:9fe5:73ec]:8333 # AS198507
+[2a07:abc4::1:946]:8333 # AS62000
+[2a09:2681:102::210]:8333 # AS61282
+[2a0a:c801:1:7::183]:8333 # AS39798
+[2a0c:5a80:1210:a800:6af7:28ff:fee5:6b3a]:8333 # AS57269
+[2a0d:5600:24:a8e::a91e]:55373 # AS9009
+[2a0d:7c40:3000:b04::2]:8333 # AS54290
+[2a0d:8340:24::2]:8333 # AS50113
+[2a0f:df00:0:2010::162]:8333 # AS41281
+[2a10:3781:16b9:1:fe3f:dbff:fe04:2d4c]:8333 # AS206238
+[2a10:3781:84b:1:b123:6306:943a:f09b]:8333 # AS206238
+[2a10:d200:1:33:a6bf:1ff:fe6a:46a9]:8333 # AS212323
+[2c0f:f4c0:2202:20b0:261c:4ff:fe14:daa0]:8333 # AS327693
+[2c0f:f8f0:da51:0:70c3:eea9:9717:9579]:8333 # AS30844
-# manually added 2021-03 for minimal torv3 bootstrap support
-2g5qfdkn2vvcbqhzcyvyiitg4ceukybxklraxjnu7atlhd22gdwywaid.onion:8333
-2jmtxvyup3ijr7u6uvu7ijtnojx4g5wodvaedivbv74w4vzntxbrhvad.onion:8333
-37m62wn7dz3uqpathpc4qfmgrbupachj52nt3jbtbjugpbu54kbud7yd.onion:8333
+# manually updated 2022-08 for minimal torv3 bootstrap support
5g72ppm3krkorsfopcm2bi7wlv4ohhs4u4mlseymasn7g7zhdcyjpfid.onion:8333
-7cgwjuwi5ehvcay4tazy7ya6463bndjk6xzrttw5t3xbpq4p22q6fyid.onion:8333
-7pyrpvqdhmayxggpcyqn5l3m5vqkw3qubnmgwlpya2mdo6x7pih7r7id.onion:8333
b64xcbleqmwgq2u46bh4hegnlrzzvxntyzbmucn3zt7cssm7y4ubv3id.onion:8333
-ejxefzf5fpst4mg2rib7grksvscl7p6fvjp6agzgfc2yglxnjtxc3aid.onion:8333
fjdyxicpm4o42xmedlwl3uvk5gmqdfs5j37wir52327vncjzvtpfv7yd.onion:8333
fpz6r5ppsakkwypjcglz6gcnwt7ytfhxskkfhzu62tnylcknh3eq6pad.onion:8333
-fzhn4uoxfbfss7h7d6ffbn266ca432ekbbzvqtsdd55ylgxn4jucm5qd.onion:8333
gxo5anvfnffnftfy5frkgvplq3rpga2ie3tcblo2vl754fvnhgorn5yd.onion:8333
ifdu5qvbofrt4ekui2iyb3kbcyzcsglazhx2hn4wfskkrx2v24qxriid.onion:8333
itz3oxsihs62muvknc237xabl5f6w6rfznfhbpayrslv2j2ubels47yd.onion:8333
-lrjh6fywjqttmlifuemq3puhvmshxzzyhoqx7uoufali57eypuenzzid.onion:8333
+kpgvmscirrdqpekbqjsvw5teanhatztpp2gl6eee4zkowvwfxwenqaid.onion:8333
m7cbpjolo662uel7rpaid46as2otcj44vvwg3gccodnvaeuwbm3anbyd.onion:8333
-opnyfyeiibe5qo5a3wbxzbb4xdiagc32bbce46owmertdknta5mi7uyd.onion:8333
-owjsdxmzla6d7lrwkbmetywqym5cyswpihciesfl5qdv2vrmwsgy4uqd.onion:8333
-q7kgmd7n7h27ds4fg7wocgniuqb3oe2zxp4nfe4skd5da6wyipibqzqd.onion:8333
+mwmfluek4au6mxxpw6fy7sjhkm65bdfc7izc7lpz3trewfdghyrzsbid.onion:8333
rp7k2go3s5lyj3fnj6zn62ktarlrsft2ohlsxkyd7v3e3idqyptvread.onion:8333
-sys54sv4xv3hn3sdiv3oadmzqpgyhd4u4xphv4xqk64ckvaxzm57a7yd.onion:8333
-tddeij4qigtjr6jfnrmq6btnirmq5msgwcsdpcdjr7atftm7cxlqztid.onion:8333
-vi5bnbxkleeqi6hfccjochnn65lcxlfqs4uwgmhudph554zibiusqnad.onion:8333
-xqt25cobm5zqucac3634zfght72he6u3eagfyej5ellbhcdgos7t2had.onion:8333
-# manually added 2021-08 for minimal i2p bootstrap support
+# manually updated 2022-08 for minimal i2p bootstrap support
+255fhcp6ajvftnyo7bwz3an3t4a4brhopm3bamyh2iu5r3gnr2rq.b32.i2p:0
+27yrtht5b5bzom2w5ajb27najuqvuydtzb7bavlak25wkufec5mq.b32.i2p:0
+2el6enckmfyiwbfcwsygkwksovtynzsigmyv3bzyk7j7qqahooua.b32.i2p:0
+3gocb7wc4zvbmmebktet7gujccuux4ifk3kqilnxnj5wpdpqx2hq.b32.i2p:0
+3tns2oov4tnllntotazy6umzkq4fhkco3iu5rnkxtu3pbfzxda7q.b32.i2p:0
+4fcc23wt3hyjk3csfzcdyjz5pcwg5dzhdqgma6bch2qyiakcbboa.b32.i2p:0
+4osyqeknhx5qf3a73jeimexwclmt42cju6xdp7icja4ixxguu2hq.b32.i2p:0
+4umsi4nlmgyp4rckosg4vegd2ysljvid47zu7pqsollkaszcbpqq.b32.i2p:0
+52v6uo6crlrlhzphslyiqblirux6olgsaa45ixih7sq5np4jujaa.b32.i2p:0
+6j2ezegd3e2e2x3o3pox335f5vxfthrrigkdrbgfbdjchm5h4awa.b32.i2p:0
+6n36ljyr55szci5ygidmxqer64qr24f4qmnymnbvgehz7qinxnla.b32.i2p:0
+72yjs6mvlby3ky6mgpvvlemmwq5pfcznrzd34jkhclgrishqdxva.b32.i2p:0
+7r4ri53lby2i3xqbgpw3idvhzeku7ubhftlf72ldqkg5kde6dauq.b32.i2p:0
a5qsnv3maw77mlmmzlcglu6twje6ttctd3fhpbfwcbpmewx6fczq.b32.i2p:0
-bitcornrd36coazsbzsz4pdebyzvaplmsalq4kpoljmn6cg6x5zq.b32.i2p:0
+aovep2pco7v2k4rheofrgytbgk23eg22dczpsjqgqtxcqqvmxk6a.b32.i2p:0
+bddbsmkas3z6fakorbkfjhv77i4hv6rysyjsvrdjukxolfghc23q.b32.i2p:0
+bitcoi656nll5hu6u7ddzrmzysdtwtnzcnrjd4rfdqbeey7dmn5a.b32.i2p:0
+brifkruhlkgrj65hffybrjrjqcgdgqs2r7siizb5b2232nruik3a.b32.i2p:0
c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p:0
-dhtq2p76tyhi442aidb3vd2bv7yxxjuddpb2jydnnrl2ons5bhha.b32.i2p:0
+day3hgxyrtwjslt54sikevbhxxs4qzo7d6vi72ipmscqtq3qmijq.b32.i2p:0
+di2zq6fr3fegf2jdcd7hdwyql4umr462gonsns2nxz5qg5vz4bka.b32.i2p:0
+e55k6wu46rzp4pg5pk5npgbr3zz45bc3ihtzu2xcye5vwnzdy7pq.b32.i2p:0
+eciohu5nq7vsvwjjc52epskuk75d24iccgzmhbzrwonw6lx4gdva.b32.i2p:0
+ejlnngarmhqvune74ko7kk55xtgbz5i5ncs4vmnvjpy3l7y63xaa.b32.i2p:0
+g47cqoppu26pr4n2cfaioqx7lbdi7mea7yqhlrkdz3wjwxjxdh2a.b32.i2p:0
h3r6bkn46qxftwja53pxiykntegfyfjqtnzbm6iv6r5mungmqgmq.b32.i2p:0
-hnbbyjpxx54623l555sta7pocy3se4sdgmuebi5k6reesz5rjp6q.b32.i2p:0
+hhfi4yqkg2twqiwezrfksftjjofbyx3ojkmlnfmcwntgnrjjhkya.b32.i2p:0
+hpiibrflqkbrcshfhmrtwfyeb7mds7a3obzwrgarejevddzamvsq.b32.i2p:0
+i4pyhsfdq4247dunel7paatdaq5gusi2hnybp2yf5wxwdnrgxaqq.b32.i2p:0
+iw6tgpmbdykffceku5da6nzf2bmz66fvp5fpcvemfu3df6aq6pga.b32.i2p:0
+jkfuajo4ayvo2rbv5qdj443q6adqmnormbhsf2f7rlp5t24xomda.b32.i2p:0
jz3s4eurm5vzjresf4mwo7oni4bk36daolwxh4iqtewakylgkxmq.b32.i2p:0
-kokkmpquqlkptu5hkmzqlttsmtwxicldr4so7wqsufk6bwf32nma.b32.i2p:0
+liu75cvktv4icbctg72w7nxbk4eibt7wamizfdii4omz7gcke5vq.b32.i2p:0
+ljsquuu3y4xje6l32p32inn6r2y6ull6oocgup6jtjrohrqxbz6a.b32.i2p:0
+lrah7acdsgopybg43shadwwiv6igezaw64i6jb5muqdg7dmhj3la.b32.i2p:0
+lzuu6mjtu7vd55d2biphicihufipoa7vyym6xfnkmmlra3tiziia.b32.i2p:0
+m6bpynxkv2ktwxkg6p2gyudjfhdupb6kuzabeqdnckkdkf4kxjla.b32.i2p:0
+m6v454xd6p3bt5swujgmveklsp7lzbkqlqqfc2p36cjlwv5dbucq.b32.i2p:0
+mlgeizrroynuhpxbzeosajt5u4ddcvynxfmcbm6kwjpaufilxigq.b32.i2p:0
+ofubxr2ir7u2guzjwyrvujicivzmvinwa36nuzlrg7tnsmebal7a.b32.i2p:0
+okfxeoh6itu4f5f43dhbzvkqwfrvm5c66lj6lvjj4q2b35i4pk4q.b32.i2p:0
+oz2ia3flpm3du2tyusulrn7h7e2eo3juzkrmn34bvnrlcrugv7ia.b32.i2p:0
+qd6jlsevsexww3wefpqs7iglxb3f63y4e6ydulfzrvwflpicmdqa.b32.i2p:0
+qddg7myylinn4tw6kdjmmp6fsyetkosnrbp2gsjx77tmkqyqv6ua.b32.i2p:0
+rizfinyses2r3or4iubs5wx66gdy6mpf73w7uobfacm2l5cral3q.b32.i2p:0
+s5hhjtmlg53bko3nwwskas7xgsmeqzy6thtsj5aa64djyrljgqaq.b32.i2p:0
sedndhv5vpcgdmykyi5st4yqhdxl3hpdtglta4do435wupahhx6q.b32.i2p:0
+tsl4dlpu2id252b6crbdnblruct664se6f2iw35fuqwa3te7wcoq.b32.i2p:0
+tugq6wa2ls2bv27pr2iy3da3k5ow3fzefbcvjcr22uc7w5vmevja.b32.i2p:0
+usztavbib756k5vqggzgkyswoj6mttihjvp3c2pa642t2mb4pvsa.b32.i2p:0
+vgu6llqbyjphml25umd5ztvyxrxuplz2g74fzbx75g3kkaetoyiq.b32.i2p:0
+wjrul5jwwb4vqdmkkrjbmly7osj6amecdpsac5xvaoqrti4nb3ha.b32.i2p:0
+wvktcp7hy4l6immhi5cxyz2dlsbhhvtcmskjemrnqehacnoap23q.b32.i2p:0
wwbw7nqr3ahkqv62cuqfwgtneekvvpnuc4i4f6yo7tpoqjswvcwa.b32.i2p:0
+xlqndzjoe5nr2nsxo6xwibh44ghyz4jfqevu62xykvemextpmjbq.b32.i2p:0
+yc4xwin5ujenvcr6ynwkz7lnmmq3nmzxvfguele6ovqqpxgjvonq.b32.i2p:0
+zdoabsg7ugzothyawodjhq54nvlofa746rxfkxpnjzj6nukmha6a.b32.i2p:0
zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtya4snkoka.b32.i2p:0
+zysrlpii5ftrzivfcyhdrwpeyyqddbrdefnfu5q6otk5gtugmh2a.b32.i2p:0
# manually added 2022-01 for minimal cjdns bootstrap support
[fc32:17ea:e415:c3bf:9808:149d:b5a2:c9aa]:8333
diff --git a/contrib/seeds/nodes_main_manual.txt b/contrib/seeds/nodes_main_manual.txt
index a6e0b8763a..286448d95d 100644
--- a/contrib/seeds/nodes_main_manual.txt
+++ b/contrib/seeds/nodes_main_manual.txt
@@ -1,42 +1,77 @@
-# manually added 2021-03 for minimal torv3 bootstrap support
-2g5qfdkn2vvcbqhzcyvyiitg4ceukybxklraxjnu7atlhd22gdwywaid.onion:8333
-2jmtxvyup3ijr7u6uvu7ijtnojx4g5wodvaedivbv74w4vzntxbrhvad.onion:8333
-37m62wn7dz3uqpathpc4qfmgrbupachj52nt3jbtbjugpbu54kbud7yd.onion:8333
+# manually updated 2022-08 for minimal torv3 bootstrap support
5g72ppm3krkorsfopcm2bi7wlv4ohhs4u4mlseymasn7g7zhdcyjpfid.onion:8333
-7cgwjuwi5ehvcay4tazy7ya6463bndjk6xzrttw5t3xbpq4p22q6fyid.onion:8333
-7pyrpvqdhmayxggpcyqn5l3m5vqkw3qubnmgwlpya2mdo6x7pih7r7id.onion:8333
b64xcbleqmwgq2u46bh4hegnlrzzvxntyzbmucn3zt7cssm7y4ubv3id.onion:8333
-ejxefzf5fpst4mg2rib7grksvscl7p6fvjp6agzgfc2yglxnjtxc3aid.onion:8333
fjdyxicpm4o42xmedlwl3uvk5gmqdfs5j37wir52327vncjzvtpfv7yd.onion:8333
fpz6r5ppsakkwypjcglz6gcnwt7ytfhxskkfhzu62tnylcknh3eq6pad.onion:8333
-fzhn4uoxfbfss7h7d6ffbn266ca432ekbbzvqtsdd55ylgxn4jucm5qd.onion:8333
gxo5anvfnffnftfy5frkgvplq3rpga2ie3tcblo2vl754fvnhgorn5yd.onion:8333
ifdu5qvbofrt4ekui2iyb3kbcyzcsglazhx2hn4wfskkrx2v24qxriid.onion:8333
itz3oxsihs62muvknc237xabl5f6w6rfznfhbpayrslv2j2ubels47yd.onion:8333
-lrjh6fywjqttmlifuemq3puhvmshxzzyhoqx7uoufali57eypuenzzid.onion:8333
+kpgvmscirrdqpekbqjsvw5teanhatztpp2gl6eee4zkowvwfxwenqaid.onion:8333
m7cbpjolo662uel7rpaid46as2otcj44vvwg3gccodnvaeuwbm3anbyd.onion:8333
-opnyfyeiibe5qo5a3wbxzbb4xdiagc32bbce46owmertdknta5mi7uyd.onion:8333
-owjsdxmzla6d7lrwkbmetywqym5cyswpihciesfl5qdv2vrmwsgy4uqd.onion:8333
-q7kgmd7n7h27ds4fg7wocgniuqb3oe2zxp4nfe4skd5da6wyipibqzqd.onion:8333
+mwmfluek4au6mxxpw6fy7sjhkm65bdfc7izc7lpz3trewfdghyrzsbid.onion:8333
rp7k2go3s5lyj3fnj6zn62ktarlrsft2ohlsxkyd7v3e3idqyptvread.onion:8333
-sys54sv4xv3hn3sdiv3oadmzqpgyhd4u4xphv4xqk64ckvaxzm57a7yd.onion:8333
-tddeij4qigtjr6jfnrmq6btnirmq5msgwcsdpcdjr7atftm7cxlqztid.onion:8333
-vi5bnbxkleeqi6hfccjochnn65lcxlfqs4uwgmhudph554zibiusqnad.onion:8333
-xqt25cobm5zqucac3634zfght72he6u3eagfyej5ellbhcdgos7t2had.onion:8333
-# manually added 2021-08 for minimal i2p bootstrap support
+# manually updated 2022-08 for minimal i2p bootstrap support
+255fhcp6ajvftnyo7bwz3an3t4a4brhopm3bamyh2iu5r3gnr2rq.b32.i2p:0
+27yrtht5b5bzom2w5ajb27najuqvuydtzb7bavlak25wkufec5mq.b32.i2p:0
+2el6enckmfyiwbfcwsygkwksovtynzsigmyv3bzyk7j7qqahooua.b32.i2p:0
+3gocb7wc4zvbmmebktet7gujccuux4ifk3kqilnxnj5wpdpqx2hq.b32.i2p:0
+3tns2oov4tnllntotazy6umzkq4fhkco3iu5rnkxtu3pbfzxda7q.b32.i2p:0
+4fcc23wt3hyjk3csfzcdyjz5pcwg5dzhdqgma6bch2qyiakcbboa.b32.i2p:0
+4osyqeknhx5qf3a73jeimexwclmt42cju6xdp7icja4ixxguu2hq.b32.i2p:0
+4umsi4nlmgyp4rckosg4vegd2ysljvid47zu7pqsollkaszcbpqq.b32.i2p:0
+52v6uo6crlrlhzphslyiqblirux6olgsaa45ixih7sq5np4jujaa.b32.i2p:0
+6j2ezegd3e2e2x3o3pox335f5vxfthrrigkdrbgfbdjchm5h4awa.b32.i2p:0
+6n36ljyr55szci5ygidmxqer64qr24f4qmnymnbvgehz7qinxnla.b32.i2p:0
+72yjs6mvlby3ky6mgpvvlemmwq5pfcznrzd34jkhclgrishqdxva.b32.i2p:0
+7r4ri53lby2i3xqbgpw3idvhzeku7ubhftlf72ldqkg5kde6dauq.b32.i2p:0
a5qsnv3maw77mlmmzlcglu6twje6ttctd3fhpbfwcbpmewx6fczq.b32.i2p:0
-bitcornrd36coazsbzsz4pdebyzvaplmsalq4kpoljmn6cg6x5zq.b32.i2p:0
+aovep2pco7v2k4rheofrgytbgk23eg22dczpsjqgqtxcqqvmxk6a.b32.i2p:0
+bddbsmkas3z6fakorbkfjhv77i4hv6rysyjsvrdjukxolfghc23q.b32.i2p:0
+bitcoi656nll5hu6u7ddzrmzysdtwtnzcnrjd4rfdqbeey7dmn5a.b32.i2p:0
+brifkruhlkgrj65hffybrjrjqcgdgqs2r7siizb5b2232nruik3a.b32.i2p:0
c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p:0
-dhtq2p76tyhi442aidb3vd2bv7yxxjuddpb2jydnnrl2ons5bhha.b32.i2p:0
+day3hgxyrtwjslt54sikevbhxxs4qzo7d6vi72ipmscqtq3qmijq.b32.i2p:0
+di2zq6fr3fegf2jdcd7hdwyql4umr462gonsns2nxz5qg5vz4bka.b32.i2p:0
+e55k6wu46rzp4pg5pk5npgbr3zz45bc3ihtzu2xcye5vwnzdy7pq.b32.i2p:0
+eciohu5nq7vsvwjjc52epskuk75d24iccgzmhbzrwonw6lx4gdva.b32.i2p:0
+ejlnngarmhqvune74ko7kk55xtgbz5i5ncs4vmnvjpy3l7y63xaa.b32.i2p:0
+g47cqoppu26pr4n2cfaioqx7lbdi7mea7yqhlrkdz3wjwxjxdh2a.b32.i2p:0
h3r6bkn46qxftwja53pxiykntegfyfjqtnzbm6iv6r5mungmqgmq.b32.i2p:0
-hnbbyjpxx54623l555sta7pocy3se4sdgmuebi5k6reesz5rjp6q.b32.i2p:0
+hhfi4yqkg2twqiwezrfksftjjofbyx3ojkmlnfmcwntgnrjjhkya.b32.i2p:0
+hpiibrflqkbrcshfhmrtwfyeb7mds7a3obzwrgarejevddzamvsq.b32.i2p:0
+i4pyhsfdq4247dunel7paatdaq5gusi2hnybp2yf5wxwdnrgxaqq.b32.i2p:0
+iw6tgpmbdykffceku5da6nzf2bmz66fvp5fpcvemfu3df6aq6pga.b32.i2p:0
+jkfuajo4ayvo2rbv5qdj443q6adqmnormbhsf2f7rlp5t24xomda.b32.i2p:0
jz3s4eurm5vzjresf4mwo7oni4bk36daolwxh4iqtewakylgkxmq.b32.i2p:0
-kokkmpquqlkptu5hkmzqlttsmtwxicldr4so7wqsufk6bwf32nma.b32.i2p:0
+liu75cvktv4icbctg72w7nxbk4eibt7wamizfdii4omz7gcke5vq.b32.i2p:0
+ljsquuu3y4xje6l32p32inn6r2y6ull6oocgup6jtjrohrqxbz6a.b32.i2p:0
+lrah7acdsgopybg43shadwwiv6igezaw64i6jb5muqdg7dmhj3la.b32.i2p:0
+lzuu6mjtu7vd55d2biphicihufipoa7vyym6xfnkmmlra3tiziia.b32.i2p:0
+m6bpynxkv2ktwxkg6p2gyudjfhdupb6kuzabeqdnckkdkf4kxjla.b32.i2p:0
+m6v454xd6p3bt5swujgmveklsp7lzbkqlqqfc2p36cjlwv5dbucq.b32.i2p:0
+mlgeizrroynuhpxbzeosajt5u4ddcvynxfmcbm6kwjpaufilxigq.b32.i2p:0
+ofubxr2ir7u2guzjwyrvujicivzmvinwa36nuzlrg7tnsmebal7a.b32.i2p:0
+okfxeoh6itu4f5f43dhbzvkqwfrvm5c66lj6lvjj4q2b35i4pk4q.b32.i2p:0
+oz2ia3flpm3du2tyusulrn7h7e2eo3juzkrmn34bvnrlcrugv7ia.b32.i2p:0
+qd6jlsevsexww3wefpqs7iglxb3f63y4e6ydulfzrvwflpicmdqa.b32.i2p:0
+qddg7myylinn4tw6kdjmmp6fsyetkosnrbp2gsjx77tmkqyqv6ua.b32.i2p:0
+rizfinyses2r3or4iubs5wx66gdy6mpf73w7uobfacm2l5cral3q.b32.i2p:0
+s5hhjtmlg53bko3nwwskas7xgsmeqzy6thtsj5aa64djyrljgqaq.b32.i2p:0
sedndhv5vpcgdmykyi5st4yqhdxl3hpdtglta4do435wupahhx6q.b32.i2p:0
+tsl4dlpu2id252b6crbdnblruct664se6f2iw35fuqwa3te7wcoq.b32.i2p:0
+tugq6wa2ls2bv27pr2iy3da3k5ow3fzefbcvjcr22uc7w5vmevja.b32.i2p:0
+usztavbib756k5vqggzgkyswoj6mttihjvp3c2pa642t2mb4pvsa.b32.i2p:0
+vgu6llqbyjphml25umd5ztvyxrxuplz2g74fzbx75g3kkaetoyiq.b32.i2p:0
+wjrul5jwwb4vqdmkkrjbmly7osj6amecdpsac5xvaoqrti4nb3ha.b32.i2p:0
+wvktcp7hy4l6immhi5cxyz2dlsbhhvtcmskjemrnqehacnoap23q.b32.i2p:0
wwbw7nqr3ahkqv62cuqfwgtneekvvpnuc4i4f6yo7tpoqjswvcwa.b32.i2p:0
+xlqndzjoe5nr2nsxo6xwibh44ghyz4jfqevu62xykvemextpmjbq.b32.i2p:0
+yc4xwin5ujenvcr6ynwkz7lnmmq3nmzxvfguele6ovqqpxgjvonq.b32.i2p:0
+zdoabsg7ugzothyawodjhq54nvlofa746rxfkxpnjzj6nukmha6a.b32.i2p:0
zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtya4snkoka.b32.i2p:0
+zysrlpii5ftrzivfcyhdrwpeyyqddbrdefnfu5q6otk5gtugmh2a.b32.i2p:0
# manually added 2022-01 for minimal cjdns bootstrap support
[fc32:17ea:e415:c3bf:9808:149d:b5a2:c9aa]:8333
diff --git a/contrib/seeds/nodes_test.txt b/contrib/seeds/nodes_test.txt
index 118bec280e..5b04791d60 100644
--- a/contrib/seeds/nodes_test.txt
+++ b/contrib/seeds/nodes_test.txt
@@ -1,16 +1,89 @@
# List of fixed seed nodes for testnet
-# Onion nodes
-35k2va6vyw4oo5ly2quvcszgdqr56kcnfgcqpnpcffut4jn3mhhwgbid.onion:18333
-blo2esfvk2rr7sr4jspmu3vt2vpgr5rigflsj645fnku7v4qmljurtid.onion:18333
-fuckcswupr5rmlvx2kqqrrosxvjyong4hatmuvxsvtcwe4dsh5rus7qd.onion:18333
-gblylyacjlitd2ywdmo2qqylwtdky7kgeqfvlhiw4zdag4x62tx54hyd.onion:18333
-gzwpduv33l7yze3bcdzj3inebiyjwddjnwvnjhh5wvnv4me76mjt2kad.onion:18333
-h3rphzofxzq52tb63mg5f6kc4my3fkcrgh3m5qryeatts43iljbawiid.onion:18333
-kf4qlhek34b3kgyxyodlmvgm4bxfrjsbjtgayyaiuyhr2eoyfgtm3bad.onion:18333
+# Onion nodes, last verified 2022-08 for minimal torv3 bootstrap support
+24j74ahq6ed4wmfrghdwroyfzimlkhnrb7zh4zw3vl2allzxbjrhaqid.onion:18333
+2fy74te65gm3c3gv3u5mhwdudvbdfh6k5fdz4gduimrltjjrxftbxrqd.onion:18333
+2lsncqdflwk272dhydrxf7ikfy23ppnmm54dnynyxiym6lqf3wowrmqd.onion:18333
+33o6qaidta7s2pmltet6vynd337vamgcifhh44rehwwxqpflcjt2njid.onion:18333
+3oo6bsc5mvf6a6ypmoaikilta6ka7mbdhdwhrnqhuhjlbaxyedvfvaqd.onion:18333
+3pe3fyklipy4sppkkgnhc22kcxtt57uler5kv72t676bbrwmcseo5qad.onion:18333
+4u4mcz2sfvxs7pwcwncswgmmcdzqtzjx7ztfo332jv4pqucb22ikdhad.onion:18333
+5v3i2kfqiqwp75gznjoptss7qgrcgseceqxpzpqkd34qeqzrg726i7id.onion:18333
+5zlrxk6q24t4vz5k4ie7gtuasdjavhoelhinzimxbfhc77u7vafipsid.onion:18333
+67s3af64ehw7xnxv422axm7tns4d6kutrftc6bjq375n74q3kj4pp7ad.onion:18333
+6a4ony53julvnufo632ktgmwvhupz63wbdwx7n7qudjy32qyq6gm3bqd.onion:18333
+6ftyg3nhc6tn2hyzls6zfdsfbroczhkxtdqumqb5q4yafhy5rdpapbid.onion:18333
+7554uw5djruh34j5ddx3iprzgqgzypcjtptwoldymfbgoywqcw2wiwyd.onion:18333
+766lozlabxaqjpbqsvt6sn3c65n6gkwwhoxyvggj7nfwnmw4cpaoccad.onion:18333
+7blv5abnytdf47yvbhxmykprmvjryqob65i2jmdwq3rrajcn2iiysbqd.onion:18333
+7v2ja4igx4v5y2jr6jrr6gaxohjhlzhvgwe4avlraxchozf7ea3kruqd.onion:18333
+7zgbmtzxow2oevd5aaqtsormw7ujv4zprl3oi2355immhq4gk7cyw5ad.onion:18333
+adstabjz7ec2y3jt4w2dvummowzv7g6m2f3kajeejffuaz7ojwj6epqd.onion:18333
+aesy6tfufadkut6flu2bsqgnw2422ur2ynjalguxlzuzuktg3zehttqd.onion:18333
+alxo32b5edi3bn2e224qrgytgxxpic4knyipvpdvctfsrvcaiq5lgeyd.onion:18333
+aoeart34umoonvd2kbqr3bc4sweu6a4msh2gp4skyqvei3shzcxbgmyd.onion:18333
+aprzvj7hgctsde4mkj3ewq35gvykspjvkqiygg7bpnw5tkvse2n7rhid.onion:18333
+awpk6z3xghx6ozouhodcydaqtr6uzzbnw4creuix7mkupxoxlmhhspad.onion:18333
+ayynqazucyh2jd5rehcfggmhunqpdwzlbhzbqgy6lj4ctz2ocj7chpid.onion:18333
+b2ika53aqckv4gs7wmog3byrea2vfzm5p7ye33digcsmvvnpbyqmzoyd.onion:18333
+be7zx3hh6dlahorlvsrrgqm4oahfrgqm2tbwnbd4u53ntu5f765n6hyd.onion:18333
+bluk62wj24bsvdwh47muo54hhwsatkftiqxevt5kba7hstjoex6ueeyd.onion:18333
+bubm6fiopfzkxqrfx6vqpioe5ahlhyubz57ogsqqy4ha5pnngiqlh6id.onion:18333
+d3czabzjj57lgrsr5gawkjd7v3gznrqa7zyizqmk4lryascavmipnyad.onion:18333
+ddj4cuvb32ve5chtp6jattcdnnmxmpoofjthzi7thgxxht7yqoetj3yd.onion:18333
+dqhhlssfwmh3g6zhwxpcfbw64xz5rfikcglinbhoxv5ajv4qzicjyeid.onion:18333
+drthcyb4x4rdfekw5g7xjogxi7aqoluilgulbgwvsme3nw3oibvchbad.onion:18333
+dwb47cmqa2tjpmvjaear7gdcars2lez6niefhi4qf22qehtyta6577qd.onion:18333
+e7tkrf54ng3q5vcn5gn77zwjwm74lkfav4mwdux3pvon6yvqg3tf46qd.onion:18333
+etuymy47s3quepvdaoo72i5e5mc7uovrzu5m4jf5q6mwlwizoxy4xgid.onion:18333
+fbimesnyhzubbzqc3uaufzkbyfmnkxvypoxaveaub7rzpzh2foxrn2yd.onion:18333
+fzbrwmgwmko7quelrhfuskt3ijabac76zx7g52dfrevmhdkj6ivh7qyd.onion:18333
+gy6nih4pmp5esyvvnhlj6qvk7zkbjuoswkxffyiip3dbkvsfxwz5zcqd.onion:18333
+ha62ziqzqdogd75zg7lfh4fqrg3bim3cpqzyupo43w5pw4fen6nr2pyd.onion:18333
+hacjjgj2mbqqrthzimmi6anvin7dljjhfl3ik6ebg3w3nmgsvr3ymmqd.onion:18333
+hbkp5xwpqo4qm75kpglfrclyiuuvdgv7mtiqfys7oqks4dmpqgpeoeid.onion:18333
+hqgoy62hoqjmz37brdfvoeov3cix5fixbqjoert4ydr6herg5oc3iwyd.onion:18333
+hvbmmzvqrpgps2x5u4ip4ksf3e5m2fneac754gtnhjn2rsevni6cz3ad.onion:18333
+hw3vzp32w4h6giplue6ix445oi6wt7gmeksrznb7tdfwhkgit7gnbbad.onion:18333
+iddr66ewkhenivapgianudjkwqcp6dxtssg7ixrdot5az6uh7m5tmjqd.onion:18333
+imya36iexiiiqrkwuxxcehnv4kg5shtirwd2vg4cnjy6lfjlph3fusqd.onion:18333
+iuhhuocns7entrzlxsxktyz2ibs7hqgiggv6sauzqkzka6laslwz7oqd.onion:18333
+ji5wmshokuc63eiulzlwj2zdvnligvrwfvvc76bice3tu43wfzvpmkyd.onion:18333
+jjfuyj7krgzkmpxvn3b2j2hwlzkmze3ezy3ifwk7dnswwawgmzqhjrqd.onion:18333
+jn2p4sgfphkxpow7kjrubrbqat77kkibzqkvuwhxyalcrazwmcqeaqyd.onion:18333
+jrveyz4us6sog6e6czsvr5mvvhgzjgv4idbe4idrolmqeudvt5a2dgid.onion:18333
+jsc4frvvnl2d3bhzyofsc72xpztgm23nl4fnb4dwkzsxr6fhij2q5iyd.onion:18333
+klymxdvje7kccv3tznabo3udopsftkmjemkbi2urqxjm4hefaudejjyd.onion:18333
+kwjxlauwjtecjfsiwopbl5pvn5n6z5rz76uk6osmlurd3uyuymcw7aid.onion:18333
+lc7upz2srw2yhpcvwg4afy64ylcoo6mfwlttqj5ovuglqnhnohpi5iqd.onion:18333
+lf3mpxfyjuovcqdvinl52pvdmmda6xqyfeiarlfamdjpgy3ouzmmlbyd.onion:18333
mc7k47ndjvvhcgs54wmjzxvate4rtuybbjoryikdssjhcxlx27psbyqd.onion:18333
-mrhiniicugfo7mgrwv3wtolk3tptlcw2uq7ih6sq43fa4k4zbilut3yd.onion:18333
-uiudyws3qizgmepfoh7wwjmsoxoxut4qrmotjjhrn247xnjopr7sfcid.onion:18333
-zc2wvoqcezcrf64trji6jmhtss34a5ds5ntzdhqegzvex3ynrd7nxcad.onion:18333
-zd5m3dgdn46naj36pxvvcalfw2paecle6sdxq64ptwxtxjomkywpklqd.onion:18333
-
+mjbg3ggeuelmc7ixty3zjccyo2urg2uyherfqe7ytkm2ejkwlec7h6ad.onion:18333
+nkyqozv6kdwi423s7s2mezzguf5bafot2a3hv4ed2dbvtblisdmad4qd.onion:18333
+nvvqo4xxiwgb3y246jmcbuuveurfdq2zs3a5y7veqkeqv5jfhang7gyd.onion:18333
+o6vfovqxz3oxszfppczpjejwouobztjrgvfojc3emvhan3bkyskzhuad.onion:18333
+oaiw2lnhzgp5ry7ivzneuufmh7lfploquu2rjv5rozmlbefedsnxe5qd.onion:18333
+oln7ybci53wk4g5n42nipyixvyjxbludsbrfsmhnirb6tk7ovlikd5id.onion:18333
+otmfnhc6wrrbf2tpdy6zkisqc3r3urnsuowsnmatoto6yixaocnkseid.onion:18333
+ovc6sajbqfcbwv3wrq7ylklu6q6prvisz4jr4lyycn4kgukzjfe4mjad.onion:18333
+pm57didyzg5ljuvn5ufr5uun2iencuk3af2gzqc5zvgfh452c3rxtjyd.onion:18333
+pmismhpwug34gnqzbutranvx2wjwbshyqj4un2dyzyuvak2eh55psfyd.onion:18333
+polarisultijjhaku6z6u7jyboho5epdsg44ttebfaxmgau2z5sqolad.onion:18333
+qe2jbe447he6panfvpyqhyntf7346gmuf55bxrmdzggmgwyjsyknhxyd.onion:18333
+qz6yd5lsgdajcteoareeptwnipxsezyx5kks6ukpk5tvqinffzunqmyd.onion:18333
+rp6pn3b3oesyr2giolbysbjhqeugxntsu7crnkth4y33ok4zvcl7yrqd.onion:18333
+ujdchuw3hz5gkbouiv4p6pwbfdn7v4k6gluwvd4wiukqc7y7ow754uad.onion:18333
+vctlwaqgmu53eutz2hewuakcipfgtyljsd7czut4dd62xr3rp6fqezad.onion:18333
+vf5ur53tzmdtotvkndcgochklnuav7quqjvkc6mctqfvef6wnmn26mid.onion:18333
+wnxgjgjgplv5iu4mssyuunycvku4qnqr5t4q6cfdt47k7uwrfifuirad.onion:18333
+wpkbkdr7clw7zk3jkwiult6bf422j54u77ml4rgig2xq7icogyrcspid.onion:18333
+wzpdt24tdark26eugredddorik3tqwcj5ialtt2yim4ceiuiq7phkyqd.onion:18333
+xgapnikkbldoggjh5ewxkyauhuwnvf3xkspxroe3ojvfrk4lswkyx5yd.onion:18333
+xkvzdhcirontixbq6pjhru57bf4sgtqylvphk25csfrsy5p5ay3oc3yd.onion:18333
+xnipauenw5wnjb2zbx6v6umgvbb3g6xhf5kjo7pnyn5tdzvzaxtzicid.onion:18333
+yda7kwpii33j2qpq32ftf6lp22znknswipjwaccvsqj7l337jvfesnid.onion:18333
+z3j5foswuhpmtrg3kb56stkzmuoaesvd5jz3eztq46c4cidapglcyuad.onion:18333
+zcep44k7unwjm2wxty4ijh2e4fv5zgbrvwlctzyaqnrqhltjfzrtodad.onion:18333
+zmvizz7fd5hdue6wt3lwqumd6qwt4ijymmmotfzh75curq3mzjm53hyd.onion:18333
+zoaa3x7quyuijggii5zl4uyeioodudsgtr2uyv2qtdsslac5ukiwlxid.onion:18333
+zovauxlorl5eswumbsoxv2m5y3sm3qlk7657dcpr2uld7xf35en46sqd.onion:18333
diff --git a/contrib/signet/getcoins.py b/contrib/signet/getcoins.py
index 147d12600d..a069f5fad3 100755
--- a/contrib/signet/getcoins.py
+++ b/contrib/signet/getcoins.py
@@ -129,7 +129,7 @@ if args.captcha != '': # Retrieve a captcha
# Convert SVG image to PPM, and load it
try:
- rv = subprocess.run([args.imagemagick, 'svg:-', '-depth', '8', 'ppm:-'], input=res.content, check=True, capture_output=True)
+ rv = subprocess.run([args.imagemagick, 'svg:-', '-depth', '8', 'ppm:-'], input=res.content, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except FileNotFoundError:
raise SystemExit(f"The binary {args.imagemagick} could not be found. Please make sure ImageMagick (or a compatible fork) is installed and that the correct path is specified.")
diff --git a/contrib/signet/miner b/contrib/signet/miner
index b366b98e2d..fdcd20ae3b 100755
--- a/contrib/signet/miner
+++ b/contrib/signet/miner
@@ -4,7 +4,6 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
import argparse
-import base64
import json
import logging
import math
@@ -15,14 +14,13 @@ import sys
import time
import subprocess
-from io import BytesIO
-
PATH_BASE_CONTRIB_SIGNET = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
PATH_BASE_TEST_FUNCTIONAL = os.path.abspath(os.path.join(PATH_BASE_CONTRIB_SIGNET, "..", "..", "test", "functional"))
sys.path.insert(0, PATH_BASE_TEST_FUNCTIONAL)
-from test_framework.blocktools import WITNESS_COMMITMENT_HEADER, script_BIP34_coinbase_height # noqa: E402
-from test_framework.messages import CBlock, CBlockHeader, COutPoint, CTransaction, CTxIn, CTxInWitness, CTxOut, from_hex, deser_string, hash256, ser_compact_size, ser_string, ser_uint256, tx_from_hex, uint256_from_str # noqa: E402
+from test_framework.blocktools import get_witness_script, script_BIP34_coinbase_height # noqa: E402
+from test_framework.messages import CBlock, CBlockHeader, COutPoint, CTransaction, CTxIn, CTxInWitness, CTxOut, from_binary, from_hex, ser_string, ser_uint256, tx_from_hex # noqa: E402
+from test_framework.psbt import PSBT, PSBTMap, PSBT_GLOBAL_UNSIGNED_TX, PSBT_IN_FINAL_SCRIPTSIG, PSBT_IN_FINAL_SCRIPTWITNESS, PSBT_IN_NON_WITNESS_UTXO, PSBT_IN_SIGHASH_TYPE # noqa: E402
from test_framework.script import CScriptOp # noqa: E402
logging.basicConfig(
@@ -34,99 +32,12 @@ SIGNET_HEADER = b"\xec\xc7\xda\xa2"
PSBT_SIGNET_BLOCK = b"\xfc\x06signetb" # proprietary PSBT global field holding the block being signed
RE_MULTIMINER = re.compile("^(\d+)(-(\d+))?/(\d+)$")
-# #### some helpers that could go into test_framework
-
-# like from_hex, but without the hex part
-def FromBinary(cls, stream):
- """deserialize a binary stream (or bytes object) into an object"""
- # handle bytes object by turning it into a stream
- was_bytes = isinstance(stream, bytes)
- if was_bytes:
- stream = BytesIO(stream)
- obj = cls()
- obj.deserialize(stream)
- if was_bytes:
- assert len(stream.read()) == 0
- return obj
-
-class PSBTMap:
- """Class for serializing and deserializing PSBT maps"""
-
- def __init__(self, map=None):
- self.map = map if map is not None else {}
-
- def deserialize(self, f):
- m = {}
- while True:
- k = deser_string(f)
- if len(k) == 0:
- break
- v = deser_string(f)
- if len(k) == 1:
- k = k[0]
- assert k not in m
- m[k] = v
- self.map = m
-
- def serialize(self):
- m = b""
- for k,v in self.map.items():
- if isinstance(k, int) and 0 <= k and k <= 255:
- k = bytes([k])
- m += ser_compact_size(len(k)) + k
- m += ser_compact_size(len(v)) + v
- m += b"\x00"
- return m
-
-class PSBT:
- """Class for serializing and deserializing PSBTs"""
-
- def __init__(self):
- self.g = PSBTMap()
- self.i = []
- self.o = []
- self.tx = None
-
- def deserialize(self, f):
- assert f.read(5) == b"psbt\xff"
- self.g = FromBinary(PSBTMap, f)
- assert 0 in self.g.map
- self.tx = FromBinary(CTransaction, self.g.map[0])
- self.i = [FromBinary(PSBTMap, f) for _ in self.tx.vin]
- self.o = [FromBinary(PSBTMap, f) for _ in self.tx.vout]
- return self
-
- def serialize(self):
- assert isinstance(self.g, PSBTMap)
- assert isinstance(self.i, list) and all(isinstance(x, PSBTMap) for x in self.i)
- assert isinstance(self.o, list) and all(isinstance(x, PSBTMap) for x in self.o)
- assert 0 in self.g.map
- tx = FromBinary(CTransaction, self.g.map[0])
- assert len(tx.vin) == len(self.i)
- assert len(tx.vout) == len(self.o)
-
- psbt = [x.serialize() for x in [self.g] + self.i + self.o]
- return b"psbt\xff" + b"".join(psbt)
-
- def to_base64(self):
- return base64.b64encode(self.serialize()).decode("utf8")
-
- @classmethod
- def from_base64(cls, b64psbt):
- return FromBinary(cls, base64.b64decode(b64psbt))
-
-# #####
-
def create_coinbase(height, value, spk):
cb = CTransaction()
cb.vin = [CTxIn(COutPoint(0, 0xffffffff), script_BIP34_coinbase_height(height), 0xffffffff)]
cb.vout = [CTxOut(value, spk)]
return cb
-def get_witness_script(witness_root, witness_nonce):
- commitment = uint256_from_str(hash256(ser_uint256(witness_root) + ser_uint256(witness_nonce)))
- return b"\x6a" + CScriptOp.encode_op_pushdata(WITNESS_COMMITMENT_HEADER + ser_uint256(commitment))
-
def signet_txs(block, challenge):
# assumes signet solution has not been added yet so does not need
# to be removed
@@ -163,11 +74,11 @@ def signet_txs(block, challenge):
def do_createpsbt(block, signme, spendme):
psbt = PSBT()
- psbt.g = PSBTMap( {0: signme.serialize(),
+ psbt.g = PSBTMap( {PSBT_GLOBAL_UNSIGNED_TX: signme.serialize(),
PSBT_SIGNET_BLOCK: block.serialize()
} )
- psbt.i = [ PSBTMap( {0: spendme.serialize(),
- 3: bytes([1,0,0,0])})
+ psbt.i = [ PSBTMap( {PSBT_IN_NON_WITNESS_UTXO: spendme.serialize(),
+ PSBT_IN_SIGHASH_TYPE: bytes([1,0,0,0])})
]
psbt.o = [ PSBTMap() ]
return psbt.to_base64()
@@ -179,10 +90,10 @@ def do_decode_psbt(b64psbt):
assert len(psbt.tx.vout) == 1
assert PSBT_SIGNET_BLOCK in psbt.g.map
- scriptSig = psbt.i[0].map.get(7, b"")
- scriptWitness = psbt.i[0].map.get(8, b"\x00")
+ scriptSig = psbt.i[0].map.get(PSBT_IN_FINAL_SCRIPTSIG, b"")
+ scriptWitness = psbt.i[0].map.get(PSBT_IN_FINAL_SCRIPTWITNESS, b"\x00")
- return FromBinary(CBlock, psbt.g.map[PSBT_SIGNET_BLOCK]), ser_string(scriptSig) + scriptWitness
+ return from_binary(CBlock, psbt.g.map[PSBT_SIGNET_BLOCK]), ser_string(scriptSig) + scriptWitness
def finish_block(block, signet_solution, grind_cmd):
block.vtx[0].vout[-1].scriptPubKey += CScriptOp.encode_op_pushdata(SIGNET_HEADER + signet_solution)
@@ -222,7 +133,7 @@ def generate_psbt(tmpl, reward_spk, *, blocktime=None):
cbwit = CTxInWitness()
cbwit.scriptWitness.stack = [ser_uint256(witnonce)]
block.vtx[0].wit.vtxinwit = [cbwit]
- block.vtx[0].vout.append(CTxOut(0, get_witness_script(witroot, witnonce)))
+ block.vtx[0].vout.append(CTxOut(0, bytes(get_witness_script(witroot, witnonce))))
signme, spendme = signet_txs(block, signet_spk_bin)
@@ -627,5 +538,3 @@ def main():
if __name__ == "__main__":
main()
-
-
diff --git a/contrib/valgrind.supp b/contrib/valgrind.supp
index 6efe49254b..d6856b4274 100644
--- a/contrib/valgrind.supp
+++ b/contrib/valgrind.supp
@@ -65,12 +65,6 @@
obj:*/libdb_cxx-*.so
}
{
- Suppress leaks on init
- Memcheck:Leak
- ...
- fun:_Z11AppInitMainR11NodeContext
-}
-{
Suppress leaks on shutdown
Memcheck:Leak
...
@@ -83,21 +77,6 @@
obj:/usr/lib64/libgdk-3.so.0.2404.7
}
{
- Suppress leveldb warning (leveldb::InitModule()) - https://github.com/google/leveldb/issues/113
- Memcheck:Leak
- match-leak-kinds: reachable
- fun:_Znwm
- fun:_ZN7leveldbL10InitModuleEv
-}
-{
- Suppress leveldb warning (leveldb::Env::Default()) - https://github.com/google/leveldb/issues/113
- Memcheck:Leak
- match-leak-kinds: reachable
- fun:_Znwm
- ...
- fun:_ZN7leveldbL14InitDefaultEnvEv
-}
-{
Suppress leveldb leak
Memcheck:Leak
match-leak-kinds: reachable
diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys
index 2f8a21009a..5ca65e7b0d 100644
--- a/contrib/verify-commits/trusted-keys
+++ b/contrib/verify-commits/trusted-keys
@@ -1,6 +1,6 @@
71A3B16735405025D447E8F274810B012346C9A6
-133EAC179436F14A5CF1B794860FEB804E669320
B8B3F1C0E58C15DB6A81D30C3648A882F4316B9B
E777299FC265DD04793070EB944D35F9AC3DB76A
D1DBF2C4B96F2DEBF4C16654410108112E7EA81F
152812300785C96444D3334D17565732E08E5E41
+6B002C6EA3F91B1B0DF0C9BC8F617F1200A6D25C
diff --git a/depends/config.site.in b/depends/config.site.in
index 189330c42d..8f6849214d 100644
--- a/depends/config.site.in
+++ b/depends/config.site.in
@@ -84,12 +84,9 @@ fi
PKG_CONFIG="$(which pkg-config) --static"
-# These two need to remain exported because pkg-config does not see them
-# otherwise. That means they must be unexported at the end of configure.ac to
-# avoid ruining the cache. Sigh.
-export PKG_CONFIG_PATH="${depends_prefix}/share/pkgconfig:${depends_prefix}/lib/pkgconfig"
+PKG_CONFIG_PATH="${depends_prefix}/share/pkgconfig:${depends_prefix}/lib/pkgconfig"
if test -z "@allow_host_packages@"; then
- export PKG_CONFIG_LIBDIR="${depends_prefix}/lib/pkgconfig"
+ PKG_CONFIG_LIBDIR="${depends_prefix}/lib/pkgconfig"
fi
CPPFLAGS="-I${depends_prefix}/include/ ${CPPFLAGS}"
@@ -105,7 +102,7 @@ PYTHONPATH="${depends_prefix}/native/lib/python3/dist-packages${PYTHONPATH:+${PA
if test -n "@AR@"; then
AR="@AR@"
- ac_cv_path_ac_pt_AR="${AR}"
+ ac_cv_path_AR="${AR}"
fi
if test -n "@RANLIB@"; then
@@ -126,17 +123,17 @@ fi
if test "@host_os@" = darwin; then
if test -n "@OTOOL@"; then
OTOOL="@OTOOL@"
- ac_cv_path_ac_pt_OTOOL="${OTOOL}"
+ ac_cv_path_OTOOL="${OTOOL}"
fi
if test -n "@INSTALL_NAME_TOOL@"; then
INSTALL_NAME_TOOL="@INSTALL_NAME_TOOL@"
- ac_cv_path_ac_pt_INSTALL_NAME_TOOL="${INSTALL_NAME_TOOL}"
+ ac_cv_path_INSTALL_NAME_TOOL="${INSTALL_NAME_TOOL}"
fi
if test -n "@DSYMUTIL@"; then
DSYMUTIL="@DSYMUTIL@"
- ac_cv_path_ac_pt_DSYMUTIL="${DSYMUTIL}"
+ ac_cv_path_DSYMUTIL="${DSYMUTIL}"
fi
fi
diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk
index 8507e28532..8fcea35d98 100644
--- a/depends/hosts/darwin.mk
+++ b/depends/hosts/darwin.mk
@@ -17,6 +17,7 @@ darwin_native_toolchain=native_cctools
clang_prog=$(build_prefix)/bin/clang
clangxx_prog=$(clang_prog)++
+llvm_config_prog=$(build_prefix)/bin/llvm-config
clang_resource_dir=$(build_prefix)/lib/clang/$(native_clang_version)
else
@@ -34,8 +35,10 @@ darwin_native_toolchain=
# Source: https://lists.gnu.org/archive/html/bug-make/2017-11/msg00017.html
clang_prog=$(shell $(SHELL) $(.SHELLFLAGS) "command -v clang")
clangxx_prog=$(shell $(SHELL) $(.SHELLFLAGS) "command -v clang++")
+llvm_config_prog=$(shell $(SHELL) $(.SHELLFLAGS) "command -v llvm-config")
clang_resource_dir=$(shell clang -print-resource-dir)
+llvm_lib_dir=$(shell $(llvm_config_prog) --libdir)
endif
cctools_TOOLS=AR RANLIB STRIP NM LIBTOOL OTOOL INSTALL_NAME_TOOL DSYMUTIL
diff --git a/depends/hosts/default.mk b/depends/hosts/default.mk
index ea60f025de..7c76331ab4 100644
--- a/depends/hosts/default.mk
+++ b/depends/hosts/default.mk
@@ -9,6 +9,7 @@ default_host_RANLIB = $(host_toolchain)ranlib
default_host_STRIP = $(host_toolchain)strip
default_host_LIBTOOL = $(host_toolchain)libtool
default_host_NM = $(host_toolchain)nm
+default_host_OBJCOPY = $(host_toolchain)objcopy
define add_host_tool_func
ifneq ($(filter $(origin $1),undefined default),)
@@ -33,5 +34,5 @@ host_$1 = $$($(host_arch)_$(host_os)_$1)
host_$(release_type)_$1 = $$($(host_arch)_$(host_os)_$(release_type)_$1)
endef
-$(foreach tool,CC CXX AR RANLIB STRIP NM LIBTOOL OTOOL INSTALL_NAME_TOOL DSYMUTIL,$(eval $(call add_host_tool_func,$(tool))))
+$(foreach tool,CC CXX AR RANLIB STRIP LIBTOOL NM OBJCOPY OTOOL INSTALL_NAME_TOOL DSYMUTIL,$(eval $(call add_host_tool_func,$(tool))))
$(foreach flags,CFLAGS CXXFLAGS CPPFLAGS LDFLAGS, $(eval $(call add_host_flags_func,$(flags))))
diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk
index b101043439..635d3d16da 100644
--- a/depends/hosts/linux.mk
+++ b/depends/hosts/linux.mk
@@ -5,6 +5,10 @@ ifneq ($(LTO),)
linux_CFLAGS += -flto
linux_CXXFLAGS += -flto
linux_LDFLAGS += -flto
+
+linux_AR = $(host_toolchain)gcc-ar
+linux_NM = $(host_toolchain)gcc-nm
+linux_RANLIB = $(host_toolchain)gcc-ranlib
endif
linux_release_CFLAGS=-O2
diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk
index b98f9ab7ac..fc1cc1afbe 100644
--- a/depends/hosts/mingw32.mk
+++ b/depends/hosts/mingw32.mk
@@ -9,6 +9,10 @@ ifneq ($(LTO),)
mingw32_CFLAGS += -flto
mingw32_CXXFLAGS += -flto
mingw32_LDFLAGS += -flto
+
+mingw32_AR = $(host_toolchain)gcc-ar
+mingw32_NM = $(host_toolchain)gcc-nm
+mingw32_RANLIB = $(host_toolchain)gcc-ranlib
endif
mingw32_release_CFLAGS=-O2
diff --git a/depends/hosts/netbsd.mk b/depends/hosts/netbsd.mk
index 8342dcc6ed..14121dca20 100644
--- a/depends/hosts/netbsd.mk
+++ b/depends/hosts/netbsd.mk
@@ -5,6 +5,10 @@ ifneq ($(LTO),)
netbsd_CFLAGS += -flto
netbsd_CXXFLAGS += -flto
netbsd_LDFLAGS += -flto
+
+netbsd_AR = $(host_toolchain)gcc-ar
+netbsd_NM = $(host_toolchain)gcc-nm
+netbsd_RANLIB = $(host_toolchain)gcc-ranlib
endif
netbsd_CXXFLAGS=$(netbsd_CFLAGS)
diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk
index 80c7ce8429..2370c5b759 100644
--- a/depends/packages/bdb.mk
+++ b/depends/packages/bdb.mk
@@ -14,7 +14,7 @@ $(package)_config_opts_freebsd=--with-pic
$(package)_config_opts_netbsd=--with-pic
$(package)_config_opts_openbsd=--with-pic
$(package)_config_opts_android=--with-pic
-$(package)_cflags+=-Wno-error=implicit-function-declaration
+$(package)_cflags+=-Wno-error=implicit-function-declaration -Wno-error=format-security
$(package)_cppflags_mingw32=-DUNICODE -D_UNICODE
endef
diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk
index 50791ebc6e..bb203d06f8 100644
--- a/depends/packages/expat.mk
+++ b/depends/packages/expat.mk
@@ -1,14 +1,18 @@
package=expat
-$(package)_version=2.4.1
+$(package)_version=2.4.8
$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_$(subst .,_,$($(package)_version))/
$(package)_file_name=$(package)-$($(package)_version).tar.xz
-$(package)_sha256_hash=cf032d0dba9b928636548e32b327a2d66b1aab63c4f4a13dd132c2d1d2f2fb6a
+$(package)_sha256_hash=f79b8f904b749e3e0d20afeadecf8249c55b2e32d4ebb089ae378df479dcaf25
+# -D_DEFAULT_SOURCE defines __USE_MISC, which exposes additional
+# definitions in endian.h, which are required for a working
+# endianess check in configure when building with -flto.
define $(package)_set_vars
$(package)_config_opts=--disable-shared --without-docbook --without-tests --without-examples
$(package)_config_opts += --disable-dependency-tracking --enable-option-checking
$(package)_config_opts += --without-xmlwf
$(package)_config_opts_linux=--with-pic
+ $(package)_cppflags += -D_DEFAULT_SOURCE
endef
define $(package)_config_cmds
diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk
index 1efe6220d3..5bd12522a7 100644
--- a/depends/packages/libevent.mk
+++ b/depends/packages/libevent.mk
@@ -37,5 +37,6 @@ endef
define $(package)_postprocess_cmds
rm lib/*.la && \
- rm include/ev*.h
+ rm include/ev*.h && \
+ rm include/event2/*_compat.h
endef
diff --git a/depends/packages/libxcb.mk b/depends/packages/libxcb.mk
index fa30e80f5c..036eaf6560 100644
--- a/depends/packages/libxcb.mk
+++ b/depends/packages/libxcb.mk
@@ -4,6 +4,7 @@ $(package)_download_path=https://xcb.freedesktop.org/dist
$(package)_file_name=$(package)-$($(package)_version).tar.xz
$(package)_sha256_hash=a55ed6db98d43469801262d81dc2572ed124edc3db31059d4e9916eb9f844c34
$(package)_dependencies=xcb_proto libXau
+$(package)_patches = remove_pthread_stubs.patch
define $(package)_set_vars
$(package)_config_opts=--disable-static --disable-devel-docs --without-doxygen --without-launchd
@@ -20,7 +21,7 @@ endef
define $(package)_preprocess_cmds
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub build-aux && \
- sed "s/pthread-stubs//" -i configure
+ patch -p1 -i $($(package)_patch_dir)/remove_pthread_stubs.patch
endef
define $(package)_config_cmds
diff --git a/depends/packages/libxkbcommon.mk b/depends/packages/libxkbcommon.mk
index 8c6c56545f..bcdcf671f7 100644
--- a/depends/packages/libxkbcommon.mk
+++ b/depends/packages/libxkbcommon.mk
@@ -5,9 +5,14 @@ $(package)_file_name=$(package)-$($(package)_version).tar.xz
$(package)_sha256_hash=60ddcff932b7fd352752d51a5c4f04f3d0403230a584df9a2e0d5ed87c486c8b
$(package)_dependencies=libxcb
+# This package explicitly enables -Werror=array-bounds, which causes build failures
+# with GCC 12.1+. Work around that by turning errors back into warnings.
+# This workaround would be dropped if the package was updated, as that would require
+# a different build system (Meson)
define $(package)_set_vars
$(package)_config_opts = --enable-option-checking --disable-dependency-tracking
$(package)_config_opts += --disable-static --disable-docs
+$(package)_cflags += -Wno-error=array-bounds
endef
define $(package)_preprocess_cmds
diff --git a/depends/packages/native_cctools.mk b/depends/packages/native_cctools.mk
index d169eb6723..03e9002ecd 100644
--- a/depends/packages/native_cctools.mk
+++ b/depends/packages/native_cctools.mk
@@ -7,18 +7,24 @@ $(package)_build_subdir=cctools
$(package)_dependencies=native_libtapi
define $(package)_set_vars
- $(package)_config_opts=--target=$(host)
+ $(package)_config_opts=--target=$(host) --enable-lto-support
+ $(package)_config_opts+=--with-llvm-config=$(llvm_config_prog)
$(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib
- ifeq ($(strip $(FORCE_USE_SYSTEM_CLANG)),)
- $(package)_config_opts+=--enable-lto-support --with-llvm-config=$(build_prefix)/bin/llvm-config
- endif
$(package)_cc=$(clang_prog)
$(package)_cxx=$(clangxx_prog)
endef
+ifneq ($(strip $(FORCE_USE_SYSTEM_CLANG)),)
define $(package)_preprocess_cmds
+ mkdir -p $($(package)_staging_prefix_dir)/lib && \
+ cp $(llvm_lib_dir)/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub cctools
endef
+else
+define $(package)_preprocess_cmds
+ cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub cctools
+endef
+endif
define $(package)_config_cmds
$($(package)_autoconf)
diff --git a/depends/packages/native_clang.mk b/depends/packages/native_clang.mk
index 245269a9d3..f2712294ab 100644
--- a/depends/packages/native_clang.mk
+++ b/depends/packages/native_clang.mk
@@ -16,10 +16,13 @@ endef
define $(package)_stage_cmds
mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_version)/include && \
mkdir -p $($(package)_staging_prefix_dir)/bin && \
+ mkdir -p $($(package)_staging_prefix_dir)/include/llvm-c && \
cp bin/clang $($(package)_staging_prefix_dir)/bin/ && \
cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ && \
cp bin/dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \
cp bin/llvm-config $($(package)_staging_prefix_dir)/bin/ && \
+ cp include/llvm-c/ExternC.h $($(package)_staging_prefix_dir)/include/llvm-c && \
+ cp include/llvm-c/lto.h $($(package)_staging_prefix_dir)/include/llvm-c && \
cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \
cp -r lib/clang/$($(package)_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_version)/include/
endef
diff --git a/depends/packages/native_ds_store.mk b/depends/packages/native_ds_store.mk
index 44108925a4..51a95f48ef 100644
--- a/depends/packages/native_ds_store.mk
+++ b/depends/packages/native_ds_store.mk
@@ -1,6 +1,6 @@
package=native_ds_store
$(package)_version=1.3.0
-$(package)_download_path=https://github.com/al45tair/ds_store/archive/
+$(package)_download_path=https://github.com/dmgbuild/ds_store/archive/
$(package)_file_name=v$($(package)_version).tar.gz
$(package)_sha256_hash=76b3280cd4e19e5179defa23fb594a9dd32643b0c80d774bd3108361d94fb46d
$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
diff --git a/depends/packages/native_libtapi.mk b/depends/packages/native_libtapi.mk
index 1633213a42..052bb23689 100644
--- a/depends/packages/native_libtapi.mk
+++ b/depends/packages/native_libtapi.mk
@@ -13,7 +13,5 @@ define $(package)_build_cmds
endef
define $(package)_stage_cmds
- ./install.sh && \
- mkdir -p $($(package)_staging_prefix_dir)/include/llvm-c && \
- cp src/llvm/include/llvm-c/lto.h $($(package)_staging_prefix_dir)/include/llvm-c
+ ./install.sh
endef
diff --git a/depends/packages/native_mac_alias.mk b/depends/packages/native_mac_alias.mk
index 783f87ca7c..ddd631186e 100644
--- a/depends/packages/native_mac_alias.mk
+++ b/depends/packages/native_mac_alias.mk
@@ -1,6 +1,6 @@
package=native_mac_alias
$(package)_version=2.2.0
-$(package)_download_path=https://github.com/al45tair/mac_alias/archive/
+$(package)_download_path=https://github.com/dmgbuild/mac_alias/archive/
$(package)_file_name=v$($(package)_version).tar.gz
$(package)_sha256_hash=421e6d7586d1f155c7db3e7da01ca0dacc9649a509a253ad7077b70174426499
$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 7e268fe9a5..d9ae918d71 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -1,9 +1,9 @@
package=qt
-$(package)_version=5.15.3
+$(package)_version=5.15.5
$(package)_download_path=https://download.qt.io/official_releases/qt/5.15/$($(package)_version)/submodules
$(package)_suffix=everywhere-opensource-src-$($(package)_version).tar.xz
$(package)_file_name=qtbase-$($(package)_suffix)
-$(package)_sha256_hash=26394ec9375d52c1592bd7b689b1619c6b8dbe9b6f91fdd5c355589787f3a0b6
+$(package)_sha256_hash=0c42c799aa7c89e479a07c451bf5a301e291266ba789e81afc18f95049524edc
$(package)_linux_dependencies=freetype fontconfig libxcb libxkbcommon libxcb_util libxcb_util_render libxcb_util_keysyms libxcb_util_image libxcb_util_wm
$(package)_qt_libs=corelib network widgets gui plugins testlib
$(package)_linguist_tools = lrelease lupdate lconvert
@@ -17,16 +17,17 @@ $(package)_patches += fix_montery_include.patch
$(package)_patches += fix_android_jni_static.patch
$(package)_patches += dont_hardcode_pwd.patch
$(package)_patches += qtbase-moc-ignore-gcc-macro.patch
-$(package)_patches += fix_limits_header.patch
$(package)_patches += use_android_ndk23.patch
$(package)_patches += rcc_hardcode_timestamp.patch
$(package)_patches += duplicate_lcqpafonts.patch
+$(package)_patches += fast_fixed_dtoa_no_optimize.patch
+$(package)_patches += guix_cross_lib_path.patch
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
-$(package)_qttranslations_sha256_hash=5d7869f670a135ad0986e266813b9dd5bbae2b09577338f9cdf8904d4af52db0
+$(package)_qttranslations_sha256_hash=c92af4171397a0ed272330b4fa0669790fcac8d050b07c8b8cc565ebeba6735e
$(package)_qttools_file_name=qttools-$($(package)_suffix)
-$(package)_qttools_sha256_hash=463b2fe71a085e7ab4e39333ae360ab0ec857b966d7a08f752c427e5df55f90d
+$(package)_qttools_sha256_hash=6d0778b71b2742cb527561791d1d3d255366163d54a10f78c683a398f09ffc6c
$(package)_extra_sources = $($(package)_qttranslations_file_name)
$(package)_extra_sources += $($(package)_qttools_file_name)
@@ -55,6 +56,7 @@ $(package)_config_opts += -no-linuxfb
$(package)_config_opts += -no-libjpeg
$(package)_config_opts += -no-libproxy
$(package)_config_opts += -no-libudev
+$(package)_config_opts += -no-mimetype-database
$(package)_config_opts += -no-mtdev
$(package)_config_opts += -no-openssl
$(package)_config_opts += -no-openvg
@@ -130,6 +132,9 @@ $(package)_config_opts_darwin += -no-feature-corewlan
$(package)_config_opts_darwin += -no-freetype
$(package)_config_opts_darwin += QMAKE_MACOSX_DEPLOYMENT_TARGET=$(OSX_MIN_VERSION)
+# Optimizing using > -O1 causes non-determinism when building across arches.
+$(package)_config_opts_aarch64_darwin += "QMAKE_CFLAGS_OPTIMIZE_FULL = -O1"
+
ifneq ($(build_os),darwin)
$(package)_config_opts_darwin += -xplatform macx-clang-linux
$(package)_config_opts_darwin += -device-option MAC_SDK_PATH=$(OSX_SDK)
@@ -152,18 +157,13 @@ $(package)_config_opts_linux += -fontconfig
$(package)_config_opts_linux += -no-opengl
$(package)_config_opts_linux += -no-feature-vulkan
$(package)_config_opts_linux += -dbus-runtime
-$(package)_config_opts_arm_linux += -platform linux-g++ -xplatform bitcoin-linux-g++
-$(package)_config_opts_i686_linux = -xplatform linux-g++-32
+ifneq ($(LTO),)
+$(package)_config_opts_linux += -ltcg
+endif
+$(package)_config_opts_linux += -platform linux-g++ -xplatform bitcoin-linux-g++
ifneq (,$(findstring -stdlib=libc++,$($(1)_cxx)))
$(package)_config_opts_x86_64_linux = -xplatform linux-clang-libc++
-else
-$(package)_config_opts_x86_64_linux = -xplatform linux-g++-64
endif
-$(package)_config_opts_aarch64_linux = -xplatform linux-aarch64-gnu-g++
-$(package)_config_opts_powerpc64_linux = -platform linux-g++ -xplatform bitcoin-linux-g++
-$(package)_config_opts_powerpc64le_linux = -platform linux-g++ -xplatform bitcoin-linux-g++
-$(package)_config_opts_riscv64_linux = -platform linux-g++ -xplatform bitcoin-linux-g++
-$(package)_config_opts_s390x_linux = -platform linux-g++ -xplatform bitcoin-linux-g++
$(package)_config_opts_mingw32 = -no-opengl
$(package)_config_opts_mingw32 += -no-dbus
@@ -173,6 +173,7 @@ $(package)_config_opts_mingw32 += "QMAKE_CFLAGS = '$($(package)_cflags) $($(pack
$(package)_config_opts_mingw32 += "QMAKE_CXX = '$($(package)_cxx)'"
$(package)_config_opts_mingw32 += "QMAKE_CXXFLAGS = '$($(package)_cxxflags) $($(package)_cppflags)'"
$(package)_config_opts_mingw32 += "QMAKE_LFLAGS = '$($(package)_ldflags)'"
+$(package)_config_opts_mingw32 += "QMAKE_LIB = '$($(package)_ar) rc'"
$(package)_config_opts_mingw32 += -device-option CROSS_COMPILE="$(host)-"
$(package)_config_opts_mingw32 += -pch
@@ -222,18 +223,11 @@ endef
# 2. Create a macOS-Clang-Linux mkspec using our mac-qmake.conf.
#
# 3. After making a copy of the mkspec for the linux-arm-gnueabi host, named
-# bitcoin-linux-g++, replace instances of linux-arm-gnueabi with $(host). This
-# way we can generically support hosts like riscv64-linux-gnu, which Qt doesn't
-# ship a mkspec for. See it's usage in config_opts_* above.
+# bitcoin-linux-g++, replace tool names with $($($(package)_type)_TOOL).
#
# 4. Put our C, CXX and LD FLAGS into gcc-base.conf. Only used for non-host builds.
#
-# 5. Do similar for the win32-g++ mkspec.
-#
-# 6. In clang.conf, swap out clang & clang++, for our compiler + flags. See #17466.
-#
-# 7. Adjust a regex in toolchain.prf, to accommodate Guix's usage of
-# CROSS_LIBRARY_PATH. See #15277.
+# 5. In clang.conf, swap out clang & clang++, for our compiler + flags. See #17466.
define $(package)_preprocess_cmds
cp $($(package)_patch_dir)/qt.pro qt.pro && \
cp $($(package)_patch_dir)/qttools_src.pro qttools/src/src.pro && \
@@ -243,22 +237,27 @@ define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \
patch -p1 -i $($(package)_patch_dir)/dont_hardcode_x86_64.patch && \
patch -p1 -i $($(package)_patch_dir)/qtbase-moc-ignore-gcc-macro.patch && \
- patch -p1 -i $($(package)_patch_dir)/fix_limits_header.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_montery_include.patch && \
patch -p1 -i $($(package)_patch_dir)/use_android_ndk23.patch && \
patch -p1 -i $($(package)_patch_dir)/rcc_hardcode_timestamp.patch && \
patch -p1 -i $($(package)_patch_dir)/duplicate_lcqpafonts.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fast_fixed_dtoa_no_optimize.patch && \
+ patch -p1 -i $($(package)_patch_dir)/guix_cross_lib_path.patch && \
mkdir -p qtbase/mkspecs/macx-clang-linux &&\
cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\
cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \
cp -r qtbase/mkspecs/linux-arm-gnueabi-g++ qtbase/mkspecs/bitcoin-linux-g++ && \
- sed -i.old "s/arm-linux-gnueabi-/$(host)-/g" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \
+ sed -i.old "s|arm-linux-gnueabi-gcc|$($($(package)_type)_CC)|" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \
+ sed -i.old "s|arm-linux-gnueabi-g++|$($($(package)_type)_CXX)|" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \
+ sed -i.old "s|arm-linux-gnueabi-ar|$($($(package)_type)_AR)|" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \
+ sed -i.old "s|arm-linux-gnueabi-objcopy|$($($(package)_type)_OBJCOPY)|" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \
+ sed -i.old "s|arm-linux-gnueabi-nm|$($($(package)_type)_NM)|" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \
+ sed -i.old "s|arm-linux-gnueabi-strip|$($($(package)_type)_STRIP)|" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \
echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
sed -i.old "s|QMAKE_CC = \$$$$\$$$${CROSS_COMPILE}clang|QMAKE_CC = $($(package)_cc)|" qtbase/mkspecs/common/clang.conf && \
- sed -i.old "s|QMAKE_CXX = \$$$$\$$$${CROSS_COMPILE}clang++|QMAKE_CXX = $($(package)_cxx)|" qtbase/mkspecs/common/clang.conf && \
- sed -i.old "s/LIBRARY_PATH/(CROSS_)?\0/g" qtbase/mkspecs/features/toolchain.prf
+ sed -i.old "s|QMAKE_CXX = \$$$$\$$$${CROSS_COMPILE}clang++|QMAKE_CXX = $($(package)_cxx)|" qtbase/mkspecs/common/clang.conf
endef
define $(package)_config_cmds
diff --git a/depends/patches/libxcb/remove_pthread_stubs.patch b/depends/patches/libxcb/remove_pthread_stubs.patch
new file mode 100644
index 0000000000..1f32dea527
--- /dev/null
+++ b/depends/patches/libxcb/remove_pthread_stubs.patch
@@ -0,0 +1,12 @@
+Remove uneeded pthread-stubs dependency
+--- a/configure
++++ b/configure
+@@ -19695,7 +19695,7 @@ fi
+ NEEDED="xau >= 0.99.2"
+ case $host_os in
+ linux*) ;;
+- *) NEEDED="$NEEDED pthread-stubs" ;;
++ *) NEEDED="$NEEDED" ;;
+ esac
+
+ pkg_failed=no
diff --git a/depends/patches/qt/dont_hardcode_x86_64.patch b/depends/patches/qt/dont_hardcode_x86_64.patch
index 5c1e030fa4..a66426877a 100644
--- a/depends/patches/qt/dont_hardcode_x86_64.patch
+++ b/depends/patches/qt/dont_hardcode_x86_64.patch
@@ -73,7 +73,7 @@ diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/defaul
index 92a9112bca6..d888731ec8d 100644
--- old/qtbase/mkspecs/features/mac/default_post.prf
+++ new/qtbase/mkspecs/features/mac/default_post.prf
-@@ -90,6 +90,11 @@ app_extension_api_only {
+@@ -95,6 +95,11 @@ app_extension_api_only {
QMAKE_LFLAGS += $$QMAKE_CFLAGS_APPLICATION_EXTENSION
}
@@ -85,7 +85,7 @@ index 92a9112bca6..d888731ec8d 100644
macx-xcode {
qmake_pkginfo_typeinfo.name = QMAKE_PKGINFO_TYPEINFO
!isEmpty(QMAKE_PKGINFO_TYPEINFO): \
-@@ -145,9 +150,6 @@ macx-xcode {
+@@ -150,9 +155,6 @@ macx-xcode {
simulator: VALID_SIMULATOR_ARCHS = $$QMAKE_APPLE_SIMULATOR_ARCHS
VALID_ARCHS = $$VALID_DEVICE_ARCHS $$VALID_SIMULATOR_ARCHS
diff --git a/depends/patches/qt/fast_fixed_dtoa_no_optimize.patch b/depends/patches/qt/fast_fixed_dtoa_no_optimize.patch
new file mode 100644
index 0000000000..d4d6539f56
--- /dev/null
+++ b/depends/patches/qt/fast_fixed_dtoa_no_optimize.patch
@@ -0,0 +1,20 @@
+Modify the optimisation flags for FastFixedDtoa.
+This fixes a non-determinism issue in the asm produced for
+this function when cross-compiling on x86_64 and aarch64 for
+the arm-linux-gnueabihf HOST.
+
+--- a/qtbase/src/3rdparty/double-conversion/fixed-dtoa.h
++++ b/qtbase/src/3rdparty/double-conversion/fixed-dtoa.h
+@@ -48,9 +48,12 @@ namespace double_conversion {
+ //
+ // This method only works for some parameters. If it can't handle the input it
+ // returns false. The output is null-terminated when the function succeeds.
++#pragma GCC push_options
++#pragma GCC optimize ("-O1")
+ bool FastFixedDtoa(double v, int fractional_count,
+ Vector<char> buffer, int* length, int* decimal_point);
+
++#pragma GCC pop_options
+ } // namespace double_conversion
+
+ #endif // DOUBLE_CONVERSION_FIXED_DTOA_H_
diff --git a/depends/patches/qt/fix_android_jni_static.patch b/depends/patches/qt/fix_android_jni_static.patch
index 22a4d5ab0e..936b82e152 100644
--- a/depends/patches/qt/fix_android_jni_static.patch
+++ b/depends/patches/qt/fix_android_jni_static.patch
@@ -1,6 +1,6 @@
--- old/qtbase/src/plugins/platforms/android/androidjnimain.cpp
+++ new/qtbase/src/plugins/platforms/android/androidjnimain.cpp
-@@ -934,6 +934,14 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
+@@ -943,6 +943,14 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
}
diff --git a/depends/patches/qt/fix_limits_header.patch b/depends/patches/qt/fix_limits_header.patch
deleted file mode 100644
index 258128c0ca..0000000000
--- a/depends/patches/qt/fix_limits_header.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-Fix compiling with GCC 11
-
-Upstream:
- - bug report: https://bugreports.qt.io/browse/QTBUG-89977
- - fix in Qt 6.1: 813a928c7c3cf98670b6043149880ed5c955efb9
-
---- old/qtbase/src/corelib/text/qbytearraymatcher.h
-+++ new/qtbase/src/corelib/text/qbytearraymatcher.h
-@@ -42,6 +42,8 @@
-
- #include <QtCore/qbytearray.h>
-
-+#include <limits>
-+
- QT_BEGIN_NAMESPACE
-
-
-
-Upstream fix and backports:
- - Qt 6.1: 3eab20ad382569cb2c9e6ccec2322c3d08c0f716
- - Qt 6.2: 380294a5971da85010a708dc23b0edec192cbf27
- - Qt 6.3: 2b2b3155d9f6ba1e4f859741468fbc47db09292b
-
---- old/qtbase/src/corelib/tools/qoffsetstringarray_p.h
-+++ new/qtbase/src/corelib/tools/qoffsetstringarray_p.h
-@@ -55,6 +55,7 @@
-
- #include <tuple>
- #include <array>
-+#include <limits>
-
- QT_BEGIN_NAMESPACE
-
diff --git a/depends/patches/qt/guix_cross_lib_path.patch b/depends/patches/qt/guix_cross_lib_path.patch
new file mode 100644
index 0000000000..7911dc21d7
--- /dev/null
+++ b/depends/patches/qt/guix_cross_lib_path.patch
@@ -0,0 +1,17 @@
+Facilitate guix building with CROSS_LIBRARY_PATH
+
+See discussion in https://github.com/bitcoin/bitcoin/pull/15277.
+
+--- a/qtbase/mkspecs/features/toolchain.prf
++++ b/qtbase/mkspecs/features/toolchain.prf
+@@ -236,8 +236,8 @@ isEmpty($${target_prefix}.INCDIRS) {
+ add_libraries = false
+ for (line, output) {
+ line ~= s/^[ \\t]*// # remove leading spaces
+- contains(line, "LIBRARY_PATH=.*") {
+- line ~= s/^LIBRARY_PATH=// # remove leading LIBRARY_PATH=
++ contains(line, "(CROSS_)?LIBRARY_PATH=.*") {
++ line ~= s/^(CROSS_)?LIBRARY_PATH=// # remove leading (CROSS_)?LIBRARY_PATH=
+ equals(QMAKE_HOST.os, Windows): \
+ paths = $$split(line, ;)
+ else: \
diff --git a/doc/README.md b/doc/README.md
index 31c95afab0..c570432aa4 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -53,7 +53,6 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th
- [Developer Notes](developer-notes.md)
- [Productivity Notes](productivity.md)
-- [Release Notes](release-notes.md)
- [Release Process](release-process.md)
- [Source Code Documentation (External Link)](https://doxygen.bitcoincore.org/)
- [Translation Process](translation_process.md)
diff --git a/doc/bips.md b/doc/bips.md
index 0f3f61daf1..1d5c91b8bd 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -1,4 +1,4 @@
-BIPs that are implemented by Bitcoin Core (up-to-date up to **v23.0**):
+BIPs that are implemented by Bitcoin Core (up-to-date up to **v24.0**):
* [`BIP 9`](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki): The changes allowing multiple soft-forks to be deployed in parallel have been implemented since **v0.12.1** ([PR #7575](https://github.com/bitcoin/bitcoin/pull/7575))
* [`BIP 11`](https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki): Multisig outputs are standard since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)).
@@ -28,6 +28,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v23.0**):
and it is disabled by default at build time since **v0.19.0** ([PR #15584](https://github.com/bitcoin/bitcoin/pull/15584)).
It has been removed as of **v0.20.0** ([PR 17165](https://github.com/bitcoin/bitcoin/pull/17165)).
* [`BIP 84`](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki): The experimental descriptor wallets introduced in **v0.21.0** by default use the Hierarchical Deterministic Wallet derivation proposed by BIP 84. ([PR #16528](https://github.com/bitcoin/bitcoin/pull/16528))
+* [`BIP 86`](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki): Descriptor wallets by default use the Hierarchical Deterministic Wallet derivation proposed by BIP 86 since **v23.0** ([PR #22364](https://github.com/bitcoin/bitcoin/pull/22364)).
* [`BIP 90`](https://github.com/bitcoin/bips/blob/master/bip-0090.mediawiki): Trigger mechanism for activation of BIPs 34, 65, and 66 has been simplified to block height checks since **v0.14.0** ([PR #8391](https://github.com/bitcoin/bitcoin/pull/8391)).
* [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)).
* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)), and has been *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)).
@@ -58,6 +59,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v23.0**):
with mainnet activation as of **v0.21.1** ([PR 21377](https://github.com/bitcoin/bitcoin/pull/21377),
[PR 21686](https://github.com/bitcoin/bitcoin/pull/21686)).
* [`BIP 350`](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki): Addresses for native v1+ segregated Witness outputs use Bech32m instead of Bech32 as of **v22.0** ([PR 20861](https://github.com/bitcoin/bitcoin/pull/20861)).
+* [`BIP 371`](https://github.com/bitcoin/bips/blob/master/bip-0371.mediawiki): Taproot fields for PSBT as of **v24.0** ([PR 22558](https://github.com/bitcoin/bitcoin/pull/22558)).
* [`BIP 380`](https://github.com/bitcoin/bips/blob/master/bip-0380.mediawiki)
[`381`](https://github.com/bitcoin/bips/blob/master/bip-0381.mediawiki)
[`382`](https://github.com/bitcoin/bips/blob/master/bip-0382.mediawiki)
diff --git a/doc/bitcoin-conf.md b/doc/bitcoin-conf.md
index acd767f234..1ebfb4c1de 100644
--- a/doc/bitcoin-conf.md
+++ b/doc/bitcoin-conf.md
@@ -6,6 +6,8 @@ All command-line options (except for `-?`, `-help`, `-version` and `-conf`) may
Changes to the configuration file while `bitcoind` or `bitcoin-qt` is running only take effect after restarting.
+Users should never make any configuration changes which they do not understand. Furthermore, users should always be wary of accepting any configuration changes provided to them by another source (even if they believe that they do understand them).
+
## Configuration File Format
The configuration file is a plain text file and consists of `option=value` entries, one per line. Leading and trailing whitespaces are removed.
diff --git a/doc/build-netbsd.md b/doc/build-netbsd.md
index 9cec201faf..0f05cdcba7 100644
--- a/doc/build-netbsd.md
+++ b/doc/build-netbsd.md
@@ -1,92 +1,116 @@
-NetBSD Build Guide
-======================
-**Updated for NetBSD [8.0](https://www.netbsd.org/releases/formal-8/NetBSD-8.0.html)**
+# NetBSD Build Guide
-This guide describes how to build bitcoind and command-line utilities on NetBSD.
+Updated for NetBSD [9.2](https://netbsd.org/releases/formal-9/NetBSD-9.2.html).
-This guide does not contain instructions for building the GUI.
+This guide describes how to build bitcoind, command-line utilities, and GUI on NetBSD.
-Preparation
--------------
+## Preparation
-You will need the following modules, which can be installed via pkgsrc or pkgin:
+### 1. Install Required Dependencies
+
+Install the required dependencies the usual way you [install software on NetBSD](https://www.netbsd.org/docs/guide/en/chap-boot.html#chap-boot-pkgsrc).
+The example commands below use `pkgin`.
+
+```bash
+pkgin install autoconf automake libtool pkg-config git gmake boost libevent
```
-autoconf
-automake
-boost
-git
-gmake
-libevent
-libtool
-pkg-config
-python37
-git clone https://github.com/bitcoin/bitcoin.git
+NetBSD currently ships with an older version of `gcc` than is needed to build. You should upgrade your `gcc` and then pass this new version to the configure script.
+
+For example, grab `gcc9`:
+```
+pkgin install gcc9
+```
+
+Then, when configuring, pass the following:
+```bash
+./configure
+ ...
+ CC="/usr/pkg/gcc9/bin/gcc" \
+ CXX="/usr/pkg/gcc9/bin/g++" \
+ ...
```
See [dependencies.md](dependencies.md) for a complete overview.
-### Building Bitcoin Core
+### 2. Clone Bitcoin Repo
-**Important**: Use `gmake` (the non-GNU `make` will exit with an error).
+Clone the Bitcoin Core repository to a directory. All build scripts and commands will run from this directory.
-#### With descriptor wallet:
+```bash
+git clone https://github.com/bitcoin/bitcoin.git
+```
+
+### 3. Install Optional Dependencies
+
+#### Wallet Dependencies
+
+It is not necessary to build wallet functionality to run bitcoind or the GUI.
+
+###### Descriptor Wallet Support
+
+`sqlite3` is required to enable support for [descriptor wallets](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md).
-The descriptor wallet uses `sqlite3`. You can install it using:
```bash
pkgin install sqlite3
```
+###### Legacy Wallet Support
+
+`db4` is required to enable support for legacy wallets.
+
```bash
-./autogen.sh
-./configure --with-gui=no --without-bdb \
- CPPFLAGS="-I/usr/pkg/include" \
- LDFLAGS="-L/usr/pkg/lib" \
- BOOST_CPPFLAGS="-I/usr/pkg/include" \
- MAKE=gmake
+pkgin install db4
```
-#### With legacy wallet:
-
-BerkeleyDB is use for legacy wallet functionality.
+#### GUI Dependencies
-It is recommended to use Berkeley DB 4.8. You cannot use the BerkeleyDB library
-from ports.
-You can use [the installation script included in contrib/](/contrib/install_db4.sh) like so:
+Bitcoin Core includes a GUI built with the cross-platform Qt Framework. To compile the GUI, we need to install `qt5`.
```bash
-./contrib/install_db4.sh `pwd`
+pkgin install qt5
```
-from the root of the repository. Then set `BDB_PREFIX` for the next section:
+The GUI can encode addresses in a QR Code. To build in QR support for the GUI, install `qrencode`.
```bash
-export BDB_PREFIX="$PWD/db4"
+pkgin install qrencode
```
+#### Test Suite Dependencies
+
+There is an included test suite that is useful for testing code changes when developing.
+To run the test suite (recommended), you will need to have Python 3 installed:
+
```bash
-./autogen.sh
-./configure --with-gui=no CPPFLAGS="-I/usr/pkg/include" \
- LDFLAGS="-L/usr/pkg/lib" \
- BOOST_CPPFLAGS="-I/usr/pkg/include" \
- BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" \
- BDB_CFLAGS="-I${BDB_PREFIX}/include" \
- MAKE=gmake
+pkgin install python37
```
-#### Without wallet:
+### Building Bitcoin Core
+
+**Note**: Use `gmake` (the non-GNU `make` will exit with an error).
+
+
+### 1. Configuration
+
+There are many ways to configure Bitcoin Core. Here is an example that
+explicitly disables the wallet and GUI:
+
```bash
./autogen.sh
-./configure --with-gui=no --disable-wallet \
+./configure --without-wallet --with-gui=no \
CPPFLAGS="-I/usr/pkg/include" \
- LDFLAGS="-L/usr/pkg/lib" \
- BOOST_CPPFLAGS="-I/usr/pkg/include" \
MAKE=gmake
```
+For a full list of configuration options, see the output of `./configure --help`
+
+### 2. Compile
+
Build and run the tests:
+
```bash
gmake # use "-j N" here for N parallel jobs
-gmake check
+gmake check # Run tests if Python 3 is available
```
diff --git a/doc/build-osx.md b/doc/build-osx.md
index fdf0a9d414..f11ed97e09 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -96,14 +96,6 @@ Skip if you don't intend to use the GUI.
brew install qt@5
```
-Ensure that the `qt@5` package is installed, not the `qt` package.
-If 'qt' is installed, the build process will fail.
-if installed, remove the `qt` package with the following command:
-
-``` bash
-brew uninstall qt
-```
-
Note: Building with Qt binaries downloaded from the Qt website is not officially supported.
See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714).
diff --git a/doc/build-unix.md b/doc/build-unix.md
index f02729ee32..874015707a 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -277,42 +277,14 @@ A list of additional configure flags can be displayed with:
Setup and Build Example: Arch Linux
-----------------------------------
-This example lists the steps necessary to setup and build a command line only, non-wallet distribution of the latest changes on Arch Linux:
+This example lists the steps necessary to setup and build a command line only distribution of the latest changes on Arch Linux:
- pacman -S git base-devel boost libevent python
+ pacman --sync --needed autoconf automake boost gcc git libevent libtool make pkgconf python sqlite
git clone https://github.com/bitcoin/bitcoin.git
cd bitcoin/
./autogen.sh
- ./configure --disable-wallet --without-gui --without-miniupnpc
+ ./configure
make check
+ ./src/bitcoind
-Note:
-Enabling wallet support requires either compiling against a Berkeley DB newer than 4.8 (package `db`) using `--with-incompatible-bdb`,
-or building and depending on a local version of Berkeley DB 4.8. The readily available Arch Linux packages are currently built using
-`--with-incompatible-bdb` according to the [PKGBUILD](https://github.com/archlinux/svntogit-community/blob/packages/bitcoin/trunk/PKGBUILD).
-As mentioned above, when maintaining portability of the wallet between the standard Bitcoin Core distributions and independently built
-node software is desired, Berkeley DB 4.8 must be used.
-
-
-ARM Cross-compilation
--------------------
-These steps can be performed on, for example, an Ubuntu VM. The depends system
-will also work on other Linux distributions, however the commands for
-installing the toolchain will be different.
-
-Make sure you install the build requirements mentioned above.
-Then, install the toolchain and curl:
-
- sudo apt-get install g++-arm-linux-gnueabihf curl
-
-To build executables for ARM:
-
- cd depends
- make HOST=arm-linux-gnueabihf NO_QT=1
- cd ..
- ./autogen.sh
- CONFIG_SITE=$PWD/depends/arm-linux-gnueabihf/share/config.site ./configure --enable-reduce-exports LDFLAGS=-static-libstdc++
- make
-
-
-For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
+If you intend to work with legacy Berkeley DB wallets, see [Berkeley DB](#berkeley-db) section.
diff --git a/doc/dependencies.md b/doc/dependencies.md
index 697d432520..8b8259ab0a 100644
--- a/doc/dependencies.md
+++ b/doc/dependencies.md
@@ -30,7 +30,7 @@ You can find installation instructions in the `build-*.md` file for your platfor
| [Fontconfig](../depends/packages/fontconfig.mk) | [link](https://www.freedesktop.org/wiki/Software/fontconfig/) | [2.12.6](https://github.com/bitcoin/bitcoin/pull/23495) | 2.6 | Yes |
| [FreeType](../depends/packages/freetype.mk) | [link](https://freetype.org) | [2.11.0](https://github.com/bitcoin/bitcoin/commit/01544dd78ccc0b0474571da854e27adef97137fb) | 2.3.0 | Yes |
| [qrencode](../depends/packages/qrencode.mk) | [link](https://fukuchi.org/works/qrencode/) | [3.4.4](https://github.com/bitcoin/bitcoin/pull/6373) | | No |
-| [Qt](../depends/packages/qt.mk) | [link](https://download.qt.io/official_releases/qt/) | [5.15.3](https://github.com/bitcoin/bitcoin/pull/24668) | [5.11.3](https://github.com/bitcoin/bitcoin/pull/24132) | No |
+| [Qt](../depends/packages/qt.mk) | [link](https://download.qt.io/official_releases/qt/) | [5.15.5](https://github.com/bitcoin/bitcoin/pull/25719) | [5.11.3](https://github.com/bitcoin/bitcoin/pull/24132) | No |
### Networking
| Dependency | Releases | Version used | Minimum required | Runtime |
diff --git a/doc/descriptors.md b/doc/descriptors.md
index ab2face4f0..69a5ee2715 100644
--- a/doc/descriptors.md
+++ b/doc/descriptors.md
@@ -11,13 +11,16 @@ Supporting RPCs are:
addresses.
- `listunspent` outputs a specialized descriptor for the reported unspent outputs.
- `getaddressinfo` outputs a descriptor for solvable addresses (since v0.18).
-- `importmulti` takes as input descriptors to import into the wallet
+- `importmulti` takes as input descriptors to import into a legacy wallet
(since v0.18).
- `generatetodescriptor` takes as input a descriptor and generates coins to it
(`regtest` only, since v0.19).
- `utxoupdatepsbt` takes as input descriptors to add information to the psbt
(since v0.19).
-- `createmultisig` and `addmultisigaddress` return descriptors as well (since v0.20)
+- `createmultisig` and `addmultisigaddress` return descriptors as well (since v0.20).
+- `importdescriptors` takes as input descriptors to import into a descriptor wallet
+ (since v0.21).
+- `listdescriptors` outputs descriptors imported into a descriptor wallet (since v22).
This document describes the language. For the specifics on usage, see the RPC
documentation for the functions mentioned above.
@@ -77,6 +80,7 @@ Descriptors consist of several types of expressions. The top level expression is
- `tr(KEY)` or `tr(KEY,TREE)` (top level only): P2TR output with the specified key as internal key, and optionally a tree of script paths.
- `addr(ADDR)` (top level only): the script which ADDR expands to.
- `raw(HEX)` (top level only): the script whose hex encoding is HEX.
+- `rawtr(KEY)` (top level only): P2TR output with the specified key as output key. NOTE: while it's possible to use this to construct wallets, it has several downsides, like being unable to prove no hidden script path exists. Use at your own risk.
`KEY` expressions:
- Optionally, key origin information, consisting of:
@@ -87,7 +91,7 @@ Descriptors consist of several types of expressions. The top level expression is
- Followed by the actual key, which is either:
- Hex encoded public keys (either 66 characters starting with `02` or `03` for a compressed pubkey, or 130 characters starting with `04` for an uncompressed pubkey).
- Inside `wpkh` and `wsh`, only compressed public keys are permitted.
- - Inside `tr`, x-only pubkeys are also permitted (64 hex characters).
+ - Inside `tr` and `rawtr`, x-only pubkeys are also permitted (64 hex characters).
- [WIF](https://en.bitcoin.it/wiki/Wallet_import_format) encoded private keys may be specified instead of the corresponding public key, with the same meaning.
- `xpub` encoded extended public key or `xprv` encoded extended private key (as defined in [BIP 32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)).
- Followed by zero or more `/NUM` unhardened and `/NUM'` hardened BIP32 derivation steps.
diff --git a/doc/design/assumeutxo.md b/doc/design/assumeutxo.md
index 2726cf779b..c353c78ff8 100644
--- a/doc/design/assumeutxo.md
+++ b/doc/design/assumeutxo.md
@@ -41,7 +41,7 @@ be of use.
Chainstate within the system goes through a number of phases when UTXO snapshots are
used, as managed by `ChainstateManager`. At various points there can be multiple
-`CChainState` objects in existence to facilitate both maintaining the network tip and
+`Chainstate` objects in existence to facilitate both maintaining the network tip and
performing historical validation of the assumed-valid chain.
It is worth noting that though there are multiple separate chainstates, those
@@ -53,7 +53,7 @@ data.
### "Normal" operation via initial block download
-`ChainstateManager` manages a single CChainState object, for which
+`ChainstateManager` manages a single Chainstate object, for which
`m_snapshot_blockhash` is null. This chainstate is (maybe obviously)
considered active. This is the "traditional" mode of operation for bitcoind.
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 23f975df34..00c68911ef 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -386,8 +386,10 @@ Run configure with the `--enable-gprof` option, then make.
If the code is behaving strangely, take a look in the `debug.log` file in the data directory;
error and debugging messages are written there.
-The `-debug=...` command-line option controls debugging; running with just `-debug` or `-debug=1` will turn
-on all categories (and give you a very large `debug.log` file).
+Debug logging can be enabled on startup with the `-debug` and `-loglevel`
+configuration options and toggled while bitcoind is running with the `logging`
+RPC. For instance, launching bitcoind with `-debug` or `-debug=1` will turn on
+all log categories and `-loglevel=trace` will turn on all log severity levels.
The Qt code routes `qDebug()` output to `debug.log` under category "qt": run with `-debug=qt`
to see it.
@@ -603,10 +605,10 @@ Threads
: Started from `main()` in `bitcoind.cpp`. Responsible for starting up and
shutting down the application.
-- [ThreadImport (`b-loadblk`)](https://doxygen.bitcoincore.org/init_8cpp.html#ae9e290a0e829ec0198518de2eda579d1)
+- [ThreadImport (`b-loadblk`)](https://doxygen.bitcoincore.org/namespacenode.html#ab4305679079866f0f420f7dbf278381d)
: Loads blocks from `blk*.dat` files or `-loadblock=<file>` on startup.
-- [ThreadScriptCheck (`b-scriptch.x`)](https://doxygen.bitcoincore.org/validation_8cpp.html#a925a33e7952a157922b0bbb8dab29a20)
+- [CCheckQueue::Loop (`b-scriptch.x`)](https://doxygen.bitcoincore.org/class_c_check_queue.html#a6e7fa51d3a25e7cb65446d4b50e6a987)
: Parallel script validation threads for transactions in blocks.
- [ThreadHTTP (`b-http`)](https://doxygen.bitcoincore.org/httpserver_8cpp.html#abb9f6ea8819672bd9a62d3695070709c)
@@ -622,7 +624,7 @@ Threads
: Does asynchronous background tasks like dumping wallet contents, dumping
addrman and running asynchronous validationinterface callbacks.
-- [TorControlThread (`b-torcontrol`)](https://doxygen.bitcoincore.org/torcontrol_8cpp.html#a4faed3692d57a0d7bdbecf3b37f72de0)
+- [TorControlThread (`b-torcontrol`)](https://doxygen.bitcoincore.org/torcontrol_8cpp.html#a52a3efff23634500bb42c6474f306091)
: Libevent thread for tor connections.
- Net threads:
@@ -634,7 +636,7 @@ Threads
- [ThreadDNSAddressSeed (`b-dnsseed`)](https://doxygen.bitcoincore.org/class_c_connman.html#aa7c6970ed98a4a7bafbc071d24897d13)
: Loads addresses of peers from the DNS.
- - [ThreadMapPort (`b-upnp`)](https://doxygen.bitcoincore.org/net_8cpp.html#a63f82a71c4169290c2db1651a9bbe249)
+ - ThreadMapPort (`b-mapport`)
: Universal plug-and-play startup/shutdown.
- [ThreadSocketHandler (`b-net`)](https://doxygen.bitcoincore.org/class_c_connman.html#a765597cbfe99c083d8fa3d61bb464e34)
@@ -646,6 +648,9 @@ Threads
- [ThreadOpenConnections (`b-opencon`)](https://doxygen.bitcoincore.org/class_c_connman.html#a55e9feafc3bab78e5c9d408c207faa45)
: Initiates new connections to peers.
+ - [ThreadI2PAcceptIncoming (`b-i2paccept`)](https://doxygen.bitcoincore.org/class_c_connman.html#a57787b4f9ac847d24065fbb0dd6e70f8)
+ : Listens for and accepts incoming I2P connections through the I2P SAM proxy.
+
Ignoring IDE/editor files
--------------------------
@@ -957,7 +962,7 @@ void CTxMemPool::UpdateTransactionsFromBlock(...)
```C++
// validation.h
-class CChainState
+class Chainstate
{
protected:
...
@@ -978,7 +983,7 @@ public:
}
// validation.cpp
-bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
+bool Chainstate::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
{
AssertLockNotHeld(m_chainstate_mutex);
AssertLockNotHeld(::cs_main);
diff --git a/doc/i2p.md b/doc/i2p.md
index 39f65c4e5f..1599c2fe0f 100644
--- a/doc/i2p.md
+++ b/doc/i2p.md
@@ -47,9 +47,26 @@ In a typical situation, this suffices:
bitcoind -i2psam=127.0.0.1:7656
```
-The first time Bitcoin Core connects to the I2P router, its I2P address (and
-corresponding private key) will be automatically generated and saved in a file
-named `i2p_private_key` in the Bitcoin Core data directory.
+The first time Bitcoin Core connects to the I2P router, if
+`-i2pacceptincoming=1`, then it will automatically generate a persistent I2P
+address and its corresponding private key. The private key will be saved in a
+file named `i2p_private_key` in the Bitcoin Core data directory. The persistent
+I2P address is used for accepting incoming connections and for making outgoing
+connections if `-i2pacceptincoming=1`. If `-i2pacceptincoming=0` then only
+outbound I2P connections are made and a different transient I2P address is used
+for each connection to improve privacy.
+
+## Persistent vs transient I2P addresses
+
+In I2P connections, the connection receiver sees the I2P address of the
+connection initiator. This is unlike the Tor network where the recipient does
+not know who is connecting to them and can't tell if two connections are from
+the same peer or not.
+
+If an I2P node is not accepting incoming connections, then Bitcoin Core uses
+random, one-time, transient I2P addresses for itself for outbound connections
+to make it harder to discriminate, fingerprint or analyze it based on its I2P
+address.
## Additional configuration options related to I2P
@@ -85,7 +102,8 @@ one of the networks has issues.
## I2P-related information in Bitcoin Core
-There are several ways to see your I2P address in Bitcoin Core:
+There are several ways to see your I2P address in Bitcoin Core if accepting
+incoming I2P connections (`-i2pacceptincoming`):
- in the "Local addresses" output of CLI `-netinfo`
- in the "localaddresses" output of RPC `getnetworkinfo`
- in the debug log (grep for `AddLocal`; the I2P address ends in `.b32.i2p`)
diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1
index 6bcad7006b..af34832fc5 100644
--- a/doc/man/bitcoin-cli.1
+++ b/doc/man/bitcoin-cli.1
@@ -1,5 +1,181 @@
-.TH BITCOIN-CLI "1"
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
+.TH BITCOIN-CLI "1" "December 2022" "bitcoin-cli v24.0.1" "User Commands"
.SH NAME
-bitcoin-cli \- manual page for bitcoin-cli
+bitcoin-cli \- manual page for bitcoin-cli v24.0.1
+.SH SYNOPSIS
+.B bitcoin-cli
+[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR] \fI\,Send command to Bitcoin Core\/\fR
+.br
+.B bitcoin-cli
+[\fI\,options\/\fR] \fI\,-named <command> \/\fR[\fI\,name=value\/\fR]... \fI\,Send command to Bitcoin Core (with named arguments)\/\fR
+.br
+.B bitcoin-cli
+[\fI\,options\/\fR] \fI\,help List commands\/\fR
+.br
+.B bitcoin-cli
+[\fI\,options\/\fR] \fI\,help <command> Get help for a command\/\fR
+.SH DESCRIPTION
+Bitcoin Core RPC client version v24.0.1
+.SH OPTIONS
+.HP
+\-?
+.IP
+Print this help message and exit
+.HP
+\fB\-addrinfo\fR
+.IP
+Get the number of addresses known to the node, per network and total,
+after filtering for quality and recency. The total number of
+addresses known to the node may be higher.
+.HP
+\fB\-color=\fR<when>
+.IP
+Color setting for CLI output (default: auto). Valid values: always, auto
+(add color codes when standard output is connected to a terminal
+and OS is not WIN32), never.
+.HP
+\fB\-conf=\fR<file>
+.IP
+Specify configuration file. Relative paths will be prefixed by datadir
+location. (default: bitcoin.conf)
+.HP
+\fB\-datadir=\fR<dir>
+.IP
+Specify data directory
+.HP
+\fB\-generate\fR
+.IP
+Generate blocks, equivalent to RPC getnewaddress followed by RPC
+generatetoaddress. Optional positional integer arguments are
+number of blocks to generate (default: 1) and maximum iterations
+to try (default: 1000000), equivalent to RPC generatetoaddress
+nblocks and maxtries arguments. Example: bitcoin\-cli \fB\-generate\fR 4
+1000
+.HP
+\fB\-getinfo\fR
+.IP
+Get general information from the remote server. Note that unlike
+server\-side RPC calls, the results of \fB\-getinfo\fR is the result of
+multiple non\-atomic requests. Some entries in the result may
+represent results from different states (e.g. wallet balance may
+be as of a different block from the chain state reported)
+.HP
+\fB\-named\fR
+.IP
+Pass named instead of positional arguments (default: false)
+.HP
+\fB\-netinfo\fR
+.IP
+Get network peer connection information from the remote server. An
+optional integer argument from 0 to 4 can be passed for different
+peers listings (default: 0). Pass "help" for detailed help
+documentation.
+.HP
+\fB\-rpcclienttimeout=\fR<n>
+.IP
+Timeout in seconds during HTTP requests, or 0 for no timeout. (default:
+900)
+.HP
+\fB\-rpcconnect=\fR<ip>
+.IP
+Send commands to node running on <ip> (default: 127.0.0.1)
+.HP
+\fB\-rpccookiefile=\fR<loc>
+.IP
+Location of the auth cookie. Relative paths will be prefixed by a
+net\-specific datadir location. (default: data dir)
+.HP
+\fB\-rpcpassword=\fR<pw>
+.IP
+Password for JSON\-RPC connections
+.HP
+\fB\-rpcport=\fR<port>
+.IP
+Connect to JSON\-RPC on <port> (default: 8332, testnet: 18332, signet:
+38332, regtest: 18443)
+.HP
+\fB\-rpcuser=\fR<user>
+.IP
+Username for JSON\-RPC connections
+.HP
+\fB\-rpcwait\fR
+.IP
+Wait for RPC server to start
+.HP
+\fB\-rpcwaittimeout=\fR<n>
+.IP
+Timeout in seconds to wait for the RPC server to start, or 0 for no
+timeout. (default: 0)
+.HP
+\fB\-rpcwallet=\fR<walletname>
+.IP
+Send RPC for non\-default wallet on RPC server (needs to exactly match
+corresponding \fB\-wallet\fR option passed to bitcoind). This changes
+the RPC endpoint used, e.g.
+http://127.0.0.1:8332/wallet/<walletname>
+.HP
+\fB\-stdin\fR
+.IP
+Read extra arguments from standard input, one per line until EOF/Ctrl\-D
+(recommended for sensitive information such as passphrases). When
+combined with \fB\-stdinrpcpass\fR, the first line from standard input
+is used for the RPC password.
+.HP
+\fB\-stdinrpcpass\fR
+.IP
+Read RPC password from standard input as a single line. When combined
+with \fB\-stdin\fR, the first line from standard input is used for the
+RPC password. When combined with \fB\-stdinwalletpassphrase\fR,
+\fB\-stdinrpcpass\fR consumes the first line, and \fB\-stdinwalletpassphrase\fR
+consumes the second.
+.HP
+\fB\-stdinwalletpassphrase\fR
+.IP
+Read wallet passphrase from standard input as a single line. When
+combined with \fB\-stdin\fR, the first line from standard input is used
+for the wallet passphrase.
+.HP
+\fB\-version\fR
+.IP
+Print version and exit
+.PP
+Debugging/Testing options:
+.PP
+Chain selection options:
+.HP
+\fB\-chain=\fR<chain>
+.IP
+Use the chain <chain> (default: main). Allowed values: main, test,
+signet, regtest
+.HP
+\fB\-signet\fR
+.IP
+Use the signet chain. Equivalent to \fB\-chain\fR=\fI\,signet\/\fR. Note that the network
+is defined by the \fB\-signetchallenge\fR parameter
+.HP
+\fB\-signetchallenge\fR
+.IP
+Blocks must satisfy the given script to be considered valid (only for
+signet networks; defaults to the global default signet test
+network challenge)
+.HP
+\fB\-signetseednode\fR
+.IP
+Specify a seed node for the signet network, in the hostname[:port]
+format, e.g. sig.net:1234 (may be used multiple times to specify
+multiple seed nodes; defaults to the global default signet test
+network seed node(s))
+.HP
+\fB\-testnet\fR
+.IP
+Use the test chain. Equivalent to \fB\-chain\fR=\fI\,test\/\fR.
+.SH COPYRIGHT
+Copyright (C) 2009-2022 The Bitcoin Core developers
-This is a placeholder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
+Please contribute if you find Bitcoin Core useful. Visit
+<https://bitcoincore.org/> for further information about the software.
+The source code is available from <https://github.com/bitcoin/bitcoin>.
+
+This is experimental software.
+Distributed under the MIT software license, see the accompanying file COPYING
+or <https://opensource.org/licenses/MIT> \ No newline at end of file
diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1
index ff4d1d2c7a..9bbfb9fa8c 100644
--- a/doc/man/bitcoin-qt.1
+++ b/doc/man/bitcoin-qt.1
@@ -1,5 +1,818 @@
-.TH BITCOIN-QT "1"
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
+.TH BITCOIN-QT "1" "December 2022" "bitcoin-qt v24.0.1" "User Commands"
.SH NAME
-bitcoin-qt \- manual page for bitcoin-qt
+bitcoin-qt \- manual page for bitcoin-qt v24.0.1
+.SH SYNOPSIS
+.B bitcoin-qt
+[\fI\,command-line options\/\fR]
+.SH DESCRIPTION
+Bitcoin Core version v24.0.1
+.SH OPTIONS
+.HP
+\-?
+.IP
+Print this help message and exit
+.HP
+\fB\-alertnotify=\fR<cmd>
+.IP
+Execute command when an alert is raised (%s in cmd is replaced by
+message)
+.HP
+\fB\-assumevalid=\fR<hex>
+.IP
+If this block is in the chain assume that it and its ancestors are valid
+and potentially skip their script verification (0 to verify all,
+default:
+00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd,
+testnet:
+0000000000000004877fa2d36316398528de4f347df2f8a96f76613a298ce060,
+signet:
+000000d1a0e224fa4679d2fb2187ba55431c284fa1b74cbc8cfda866fd4d2c09)
+.HP
+\fB\-blockfilterindex=\fR<type>
+.IP
+Maintain an index of compact filters by block (default: 0, values:
+basic). If <type> is not supplied or if <type> = 1, indexes for
+all known types are enabled.
+.HP
+\fB\-blocknotify=\fR<cmd>
+.IP
+Execute command when the best block changes (%s in cmd is replaced by
+block hash)
+.HP
+\fB\-blockreconstructionextratxn=\fR<n>
+.IP
+Extra transactions to keep in memory for compact block reconstructions
+(default: 100)
+.HP
+\fB\-blocksdir=\fR<dir>
+.IP
+Specify directory to hold blocks subdirectory for *.dat files (default:
+<datadir>)
+.HP
+\fB\-blocksonly\fR
+.IP
+Whether to reject transactions from network peers. Automatic broadcast
+and rebroadcast of any transactions from inbound peers is
+disabled, unless the peer has the 'forcerelay' permission. RPC
+transactions are not affected. (default: 0)
+.HP
+\fB\-coinstatsindex\fR
+.IP
+Maintain coinstats index used by the gettxoutsetinfo RPC (default: 0)
+.HP
+\fB\-conf=\fR<file>
+.IP
+Specify path to read\-only configuration file. Relative paths will be
+prefixed by datadir location (only useable from command line, not
+configuration file) (default: bitcoin.conf)
+.HP
+\fB\-daemon\fR
+.IP
+Run in the background as a daemon and accept commands (default: 0)
+.HP
+\fB\-daemonwait\fR
+.IP
+Wait for initialization to be finished before exiting. This implies
+\fB\-daemon\fR (default: 0)
+.HP
+\fB\-datadir=\fR<dir>
+.IP
+Specify data directory
+.HP
+\fB\-dbcache=\fR<n>
+.IP
+Maximum database cache size <n> MiB (4 to 16384, default: 450). In
+addition, unused mempool memory is shared for this cache (see
+\fB\-maxmempool\fR).
+.HP
+\fB\-debuglogfile=\fR<file>
+.IP
+Specify location of debug log file. Relative paths will be prefixed by a
+net\-specific datadir location. (\fB\-nodebuglogfile\fR to disable;
+default: debug.log)
+.HP
+\fB\-includeconf=\fR<file>
+.IP
+Specify additional configuration file, relative to the \fB\-datadir\fR path
+(only useable from configuration file, not command line)
+.HP
+\fB\-loadblock=\fR<file>
+.IP
+Imports blocks from external file on startup
+.HP
+\fB\-maxmempool=\fR<n>
+.IP
+Keep the transaction memory pool below <n> megabytes (default: 300)
+.HP
+\fB\-maxorphantx=\fR<n>
+.IP
+Keep at most <n> unconnectable transactions in memory (default: 100)
+.HP
+\fB\-mempoolexpiry=\fR<n>
+.IP
+Do not keep transactions in the mempool longer than <n> hours (default:
+336)
+.HP
+\fB\-par=\fR<n>
+.IP
+Set the number of script verification threads (\fB\-10\fR to 15, 0 = auto, <0 =
+leave that many cores free, default: 0)
+.HP
+\fB\-persistmempool\fR
+.IP
+Whether to save the mempool on shutdown and load on restart (default: 1)
+.HP
+\fB\-pid=\fR<file>
+.IP
+Specify pid file. Relative paths will be prefixed by a net\-specific
+datadir location. (default: bitcoind.pid)
+.HP
+\fB\-prune=\fR<n>
+.IP
+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 \fB\-txindex\fR. Warning: Reverting this setting
+requires re\-downloading the entire blockchain. (default: 0 =
+disable pruning blocks, 1 = allow manual pruning via RPC, >=550 =
+automatically prune block files to stay under the specified
+target size in MiB)
+.HP
+\fB\-reindex\fR
+.IP
+Rebuild chain state and block index from the blk*.dat files on disk.
+This will also rebuild active optional indexes.
+.HP
+\fB\-reindex\-chainstate\fR
+.IP
+Rebuild chain state from the currently indexed blocks. When in pruning
+mode or if blocks on disk might be corrupted, use full \fB\-reindex\fR
+instead. Deactivate all optional indexes before running this.
+.HP
+\fB\-sandbox=\fR<mode>
+.IP
+Use the experimental syscall sandbox in the specified mode
+(\fB\-sandbox\fR=\fI\,log\-and\-abort\/\fR or \fB\-sandbox\fR=\fI\,abort\/\fR). Allow only expected
+syscalls to be used by bitcoind. Note that this is an
+experimental new feature that may cause bitcoind to exit or crash
+unexpectedly: use with caution. In the "log\-and\-abort" mode the
+invocation of an unexpected syscall results in a debug handler
+being invoked which will log the incident and terminate the
+program (without executing the unexpected syscall). In the
+"abort" mode the invocation of an unexpected syscall results in
+the entire process being killed immediately by the kernel without
+executing the unexpected syscall.
+.HP
+\fB\-settings=\fR<file>
+.IP
+Specify path to dynamic settings data file. Can be disabled with
+\fB\-nosettings\fR. File is written at runtime and not meant to be
+edited by users (use bitcoin.conf instead for custom settings).
+Relative paths will be prefixed by datadir location. (default:
+settings.json)
+.HP
+\fB\-startupnotify=\fR<cmd>
+.IP
+Execute command on startup.
+.HP
+\fB\-sysperms\fR
+.IP
+Create new files with system default permissions, instead of umask 077
+(only effective with disabled wallet functionality)
+.HP
+\fB\-txindex\fR
+.IP
+Maintain a full transaction index, used by the getrawtransaction rpc
+call (default: 0)
+.HP
+\fB\-version\fR
+.IP
+Print version and exit
+.PP
+Connection options:
+.HP
+\fB\-addnode=\fR<ip>
+.IP
+Add a node to connect to and attempt to keep the connection open (see
+the addnode RPC help for more info). This option can be specified
+multiple times to add multiple nodes; connections are limited to
+8 at a time and are counted separately from the \fB\-maxconnections\fR
+limit.
+.HP
+\fB\-asmap=\fR<file>
+.IP
+Specify asn mapping used for bucketing of the peers (default:
+ip_asn.map). Relative paths will be prefixed by the net\-specific
+datadir location.
+.HP
+\fB\-bantime=\fR<n>
+.IP
+Default duration (in seconds) of manually configured bans (default:
+86400)
+.HP
+\fB\-bind=\fR<addr>[:<port>][=onion]
+.IP
+Bind to given address and always listen on it (default: 0.0.0.0). Use
+[host]:port notation for IPv6. Append =onion to tag any incoming
+connections to that address and port as incoming Tor connections
+(default: 127.0.0.1:8334=onion, testnet: 127.0.0.1:18334=onion,
+signet: 127.0.0.1:38334=onion, regtest: 127.0.0.1:18445=onion)
+.HP
+\fB\-cjdnsreachable\fR
+.IP
+If set, then this host is configured for CJDNS (connecting to fc00::/8
+addresses would lead us to the CJDNS network, see doc/cjdns.md)
+(default: 0)
+.HP
+\fB\-connect=\fR<ip>
+.IP
+Connect only to the specified node; \fB\-noconnect\fR disables automatic
+connections (the rules for this peer are the same as for
+\fB\-addnode\fR). This option can be specified multiple times to connect
+to multiple nodes.
+.HP
+\fB\-discover\fR
+.IP
+Discover own IP addresses (default: 1 when listening and no \fB\-externalip\fR
+or \fB\-proxy\fR)
+.HP
+\fB\-dns\fR
+.IP
+Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (default: 1)
+.HP
+\fB\-dnsseed\fR
+.IP
+Query for peer addresses via DNS lookup, if low on addresses (default: 1
+unless \fB\-connect\fR used)
+.HP
+\fB\-externalip=\fR<ip>
+.IP
+Specify your own public address
+.HP
+\fB\-fixedseeds\fR
+.IP
+Allow fixed seeds if DNS seeds don't provide peers (default: 1)
+.HP
+\fB\-forcednsseed\fR
+.IP
+Always query for peer addresses via DNS lookup (default: 0)
+.HP
+\fB\-i2pacceptincoming\fR
+.IP
+If set and \fB\-i2psam\fR is also set then incoming I2P connections are
+accepted via the SAM proxy. If this is not set but \fB\-i2psam\fR is set
+then only outgoing connections will be made to the I2P network.
+Ignored if \fB\-i2psam\fR is not set. Listening for incoming I2P
+connections is done through the SAM proxy, not by binding to a
+local address and port (default: 1)
+.HP
+\fB\-i2psam=\fR<ip:port>
+.IP
+I2P SAM proxy to reach I2P peers and accept I2P connections (default:
+none)
+.HP
+\fB\-listen\fR
+.IP
+Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR)
+.HP
+\fB\-listenonion\fR
+.IP
+Automatically create Tor onion service (default: 1)
+.HP
+\fB\-maxconnections=\fR<n>
+.IP
+Maintain at most <n> connections to peers (default: 125). This limit
+does not apply to connections manually added via \fB\-addnode\fR or the
+addnode RPC, which have a separate limit of 8.
+.HP
+\fB\-maxreceivebuffer=\fR<n>
+.IP
+Maximum per\-connection receive buffer, <n>*1000 bytes (default: 5000)
+.HP
+\fB\-maxsendbuffer=\fR<n>
+.IP
+Maximum per\-connection send buffer, <n>*1000 bytes (default: 1000)
+.HP
+\fB\-maxtimeadjustment\fR
+.IP
+Maximum allowed median peer time offset adjustment. Local perspective of
+time may be influenced by outbound peers forward or backward by
+this amount (default: 4200 seconds).
+.HP
+\fB\-maxuploadtarget=\fR<n>
+.IP
+Tries to keep outbound traffic under the given target per 24h. Limit
+does not apply to peers with 'download' permission or blocks
+created within past week. 0 = no limit (default: 0M). Optional
+suffix units [k|K|m|M|g|G|t|T] (default: M). Lowercase is 1000
+base while uppercase is 1024 base
+.HP
+\fB\-natpmp\fR
+.IP
+Use NAT\-PMP to map the listening port (default: 0)
+.HP
+\fB\-networkactive\fR
+.IP
+Enable all P2P network activity (default: 1). Can be changed by the
+setnetworkactive RPC command
+.HP
+\fB\-onion=\fR<ip:port>
+.IP
+Use separate SOCKS5 proxy to reach peers via Tor onion services, set
+\fB\-noonion\fR to disable (default: \fB\-proxy\fR)
+.HP
+\fB\-onlynet=\fR<net>
+.IP
+Make automatic outbound connections only to network <net> (ipv4, ipv6,
+onion, i2p, cjdns). Inbound and manual connections are not
+affected by this option. It can be specified multiple times to
+allow multiple networks.
+.HP
+\fB\-peerblockfilters\fR
+.IP
+Serve compact block filters to peers per BIP 157 (default: 0)
+.HP
+\fB\-peerbloomfilters\fR
+.IP
+Support filtering of blocks and transaction with bloom filters (default:
+0)
+.HP
+\fB\-port=\fR<port>
+.IP
+Listen for connections on <port>. Nodes not using the default ports
+(default: 8333, testnet: 18333, signet: 38333, regtest: 18444)
+are unlikely to get incoming connections. Not relevant for I2P
+(see doc/i2p.md).
+.HP
+\fB\-proxy=\fR<ip:port>
+.IP
+Connect through SOCKS5 proxy, set \fB\-noproxy\fR to disable (default:
+disabled)
+.HP
+\fB\-proxyrandomize\fR
+.IP
+Randomize credentials for every proxy connection. This enables Tor
+stream isolation (default: 1)
+.HP
+\fB\-seednode=\fR<ip>
+.IP
+Connect to a node to retrieve peer addresses, and disconnect. This
+option can be specified multiple times to connect to multiple
+nodes.
+.HP
+\fB\-timeout=\fR<n>
+.IP
+Specify socket connection timeout in milliseconds. If an initial attempt
+to connect is unsuccessful after this amount of time, drop it
+(minimum: 1, default: 5000)
+.HP
+\fB\-torcontrol=\fR<ip>:<port>
+.IP
+Tor control port to use if onion listening enabled (default:
+127.0.0.1:9051)
+.HP
+\fB\-torpassword=\fR<pass>
+.IP
+Tor control port password (default: empty)
+.HP
+\fB\-upnp\fR
+.IP
+Use UPnP to map the listening port (default: 0)
+.HP
+\fB\-whitebind=\fR<[permissions@]addr>
+.IP
+Bind to the given address and add permission flags to the peers
+connecting to it. Use [host]:port notation for IPv6. Allowed
+permissions: bloomfilter (allow requesting BIP37 filtered blocks
+and transactions), noban (do not ban for misbehavior; implies
+download), forcerelay (relay transactions that are already in the
+mempool; implies relay), relay (relay even in \fB\-blocksonly\fR mode,
+and unlimited transaction announcements), mempool (allow
+requesting BIP35 mempool contents), download (allow getheaders
+during IBD, no disconnect after maxuploadtarget limit), addr
+(responses to GETADDR avoid hitting the cache and contain random
+records with the most up\-to\-date info). Specify multiple
+permissions separated by commas (default:
+download,noban,mempool,relay). Can be specified multiple times.
+.HP
+\fB\-whitelist=\fR<[permissions@]IP address or network>
+.IP
+Add permission flags to the peers connecting from the given IP address
+(e.g. 1.2.3.4) or CIDR\-notated network (e.g. 1.2.3.0/24). Uses
+the same permissions as \fB\-whitebind\fR. Can be specified multiple
+times.
+.PP
+Wallet options:
+.HP
+\fB\-addresstype\fR
+.IP
+What type of addresses to use ("legacy", "p2sh\-segwit", "bech32", or
+"bech32m", default: "bech32")
+.HP
+\fB\-avoidpartialspends\fR
+.IP
+Group outputs by address, selecting many (possibly all) or none, instead
+of selecting on a per\-output basis. Privacy is improved as
+addresses are mostly swept with fewer transactions and outputs
+are aggregated in clean change addresses. It may result in higher
+fees due to less optimal coin selection caused by this added
+limitation and possibly a larger\-than\-necessary number of inputs
+being used. Always enabled for wallets with "avoid_reuse"
+enabled, otherwise default: 0.
+.HP
+\fB\-changetype\fR
+.IP
+What type of change to use ("legacy", "p2sh\-segwit", "bech32", or
+"bech32m"). Default is "legacy" when \fB\-addresstype\fR=\fI\,legacy\/\fR, else it
+is an implementation detail.
+.HP
+\fB\-consolidatefeerate=\fR<amt>
+.IP
+The maximum feerate (in BTC/kvB) at which transaction building may use
+more inputs than strictly necessary so that the wallet's UTXO
+pool can be reduced (default: 0.0001).
+.HP
+\fB\-disablewallet\fR
+.IP
+Do not load the wallet and disable wallet RPC calls
+.HP
+\fB\-discardfee=\fR<amt>
+.IP
+The fee rate (in BTC/kvB) that indicates your tolerance for discarding
+change by adding it to the fee (default: 0.0001). Note: An output
+is discarded if it is dust at this rate, but we will always
+discard up to the dust relay fee and a discard fee above that is
+limited by the fee estimate for the longest target
+.HP
+\fB\-fallbackfee=\fR<amt>
+.IP
+A fee rate (in BTC/kvB) that will be used when fee estimation has
+insufficient data. 0 to entirely disable the fallbackfee feature.
+(default: 0.00)
+.HP
+\fB\-keypool=\fR<n>
+.IP
+Set key pool size to <n> (default: 1000). Warning: Smaller sizes may
+increase the risk of losing funds when restoring from an old
+backup, if none of the addresses in the original keypool have
+been used.
+.HP
+\fB\-maxapsfee=\fR<n>
+.IP
+Spend up to this amount in additional (absolute) fees (in BTC) if it
+allows the use of partial spend avoidance (default: 0.00)
+.HP
+\fB\-mintxfee=\fR<amt>
+.IP
+Fee rates (in BTC/kvB) smaller than this are considered zero fee for
+transaction creation (default: 0.00001)
+.HP
+\fB\-paytxfee=\fR<amt>
+.IP
+Fee rate (in BTC/kvB) to add to transactions you send (default: 0.00)
+.HP
+\fB\-signer=\fR<cmd>
+.IP
+External signing tool, see doc/external\-signer.md
+.HP
+\fB\-spendzeroconfchange\fR
+.IP
+Spend unconfirmed change when sending transactions (default: 1)
+.HP
+\fB\-txconfirmtarget=\fR<n>
+.IP
+If paytxfee is not set, include enough fee so transactions begin
+confirmation on average within n blocks (default: 6)
+.HP
+\fB\-wallet=\fR<path>
+.IP
+Specify wallet path to load at startup. Can be used multiple times to
+load multiple wallets. Path is to a directory containing wallet
+data and log files. If the path is not absolute, it is
+interpreted relative to <walletdir>. This only loads existing
+wallets and does not create new ones. For backwards compatibility
+this also accepts names of existing top\-level data files in
+<walletdir>.
+.HP
+\fB\-walletbroadcast\fR
+.IP
+Make the wallet broadcast transactions (default: 1)
+.HP
+\fB\-walletdir=\fR<dir>
+.IP
+Specify directory to hold wallets (default: <datadir>/wallets if it
+exists, otherwise <datadir>)
+.HP
+\fB\-walletnotify=\fR<cmd>
+.IP
+Execute command when a wallet transaction changes. %s in cmd is replaced
+by TxID, %w is replaced by wallet name, %b is replaced by the
+hash of the block including the transaction (set to 'unconfirmed'
+if the transaction is not included) and %h is replaced by the
+block height (\fB\-1\fR if not included). %w is not currently
+implemented on windows. On systems where %w is supported, it
+should NOT be quoted because this would break shell escaping used
+to invoke the command.
+.HP
+\fB\-walletrbf\fR
+.IP
+Send transactions with full\-RBF opt\-in enabled (RPC only, default: 1)
+.PP
+ZeroMQ notification options:
+.HP
+\fB\-zmqpubhashblock=\fR<address>
+.IP
+Enable publish hash block in <address>
+.HP
+\fB\-zmqpubhashblockhwm=\fR<n>
+.IP
+Set publish hash block outbound message high water mark (default: 1000)
+.HP
+\fB\-zmqpubhashtx=\fR<address>
+.IP
+Enable publish hash transaction in <address>
+.HP
+\fB\-zmqpubhashtxhwm=\fR<n>
+.IP
+Set publish hash transaction outbound message high water mark (default:
+1000)
+.HP
+\fB\-zmqpubrawblock=\fR<address>
+.IP
+Enable publish raw block in <address>
+.HP
+\fB\-zmqpubrawblockhwm=\fR<n>
+.IP
+Set publish raw block outbound message high water mark (default: 1000)
+.HP
+\fB\-zmqpubrawtx=\fR<address>
+.IP
+Enable publish raw transaction in <address>
+.HP
+\fB\-zmqpubrawtxhwm=\fR<n>
+.IP
+Set publish raw transaction outbound message high water mark (default:
+1000)
+.HP
+\fB\-zmqpubsequence=\fR<address>
+.IP
+Enable publish hash block and tx sequence in <address>
+.HP
+\fB\-zmqpubsequencehwm=\fR<n>
+.IP
+Set publish hash sequence message high water mark (default: 1000)
+.PP
+Debugging/Testing options:
+.HP
+\fB\-debug=\fR<category>
+.IP
+Output debug and trace logging (default: \fB\-nodebug\fR, supplying <category>
+is optional). If <category> is not supplied or if <category> = 1,
+output all debug and trace logging. <category> can be: addrman,
+bench, blockstorage, cmpctblock, coindb, estimatefee, http, i2p,
+ipc, leveldb, libevent, mempool, mempoolrej, net, proxy, prune,
+qt, rand, reindex, rpc, selectcoins, tor, util, validation,
+walletdb, zmq. This option can be specified multiple times to
+output multiple categories.
+.HP
+\fB\-debugexclude=\fR<category>
+.IP
+Exclude debug and trace logging for a category. Can be used in
+conjunction with \fB\-debug\fR=\fI\,1\/\fR to output debug and trace logging for
+all categories except the specified category. This option can be
+specified multiple times to exclude multiple categories.
+.HP
+\fB\-help\-debug\fR
+.IP
+Print help message with debugging options and exit
+.HP
+\fB\-logips\fR
+.IP
+Include IP addresses in debug output (default: 0)
+.HP
+\fB\-logsourcelocations\fR
+.IP
+Prepend debug output with name of the originating source location
+(source file, line number and function name) (default: 0)
+.HP
+\fB\-logthreadnames\fR
+.IP
+Prepend debug output with name of the originating thread (only available
+on platforms supporting thread_local) (default: 0)
+.HP
+\fB\-logtimestamps\fR
+.IP
+Prepend debug output with timestamp (default: 1)
+.HP
+\fB\-maxtxfee=\fR<amt>
+.IP
+Maximum total fees (in BTC) to use in a single wallet transaction;
+setting this too low may abort large transactions (default: 0.10)
+.HP
+\fB\-printtoconsole\fR
+.IP
+Send trace/debug info to console (default: 1 when no \fB\-daemon\fR. To disable
+logging to file, set \fB\-nodebuglogfile\fR)
+.HP
+\fB\-shrinkdebugfile\fR
+.IP
+Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR)
+.HP
+\fB\-uacomment=\fR<cmt>
+.IP
+Append comment to the user agent string
+.PP
+Chain selection options:
+.HP
+\fB\-chain=\fR<chain>
+.IP
+Use the chain <chain> (default: main). Allowed values: main, test,
+signet, regtest
+.HP
+\fB\-signet\fR
+.IP
+Use the signet chain. Equivalent to \fB\-chain\fR=\fI\,signet\/\fR. Note that the network
+is defined by the \fB\-signetchallenge\fR parameter
+.HP
+\fB\-signetchallenge\fR
+.IP
+Blocks must satisfy the given script to be considered valid (only for
+signet networks; defaults to the global default signet test
+network challenge)
+.HP
+\fB\-signetseednode\fR
+.IP
+Specify a seed node for the signet network, in the hostname[:port]
+format, e.g. sig.net:1234 (may be used multiple times to specify
+multiple seed nodes; defaults to the global default signet test
+network seed node(s))
+.HP
+\fB\-testnet\fR
+.IP
+Use the test chain. Equivalent to \fB\-chain\fR=\fI\,test\/\fR.
+.PP
+Node relay options:
+.HP
+\fB\-bytespersigop\fR
+.IP
+Equivalent bytes per sigop in transactions for relay and mining
+(default: 20)
+.HP
+\fB\-datacarrier\fR
+.IP
+Relay and mine data carrier transactions (default: 1)
+.HP
+\fB\-datacarriersize\fR
+.IP
+Maximum size of data in data carrier transactions we relay and mine
+(default: 83)
+.HP
+\fB\-mempoolfullrbf\fR
+.IP
+Accept transaction replace\-by\-fee without requiring replaceability
+signaling (default: 0)
+.HP
+\fB\-minrelaytxfee=\fR<amt>
+.IP
+Fees (in BTC/kvB) smaller than this are considered zero fee for
+relaying, mining and transaction creation (default: 0.00001)
+.HP
+\fB\-permitbaremultisig\fR
+.IP
+Relay non\-P2SH multisig (default: 1)
+.HP
+\fB\-whitelistforcerelay\fR
+.IP
+Add 'forcerelay' permission to whitelisted inbound peers with default
+permissions. This will relay transactions even if the
+transactions were already in the mempool. (default: 0)
+.HP
+\fB\-whitelistrelay\fR
+.IP
+Add 'relay' permission to whitelisted inbound peers with default
+permissions. This will accept relayed transactions even when not
+relaying transactions (default: 1)
+.PP
+Block creation options:
+.HP
+\fB\-blockmaxweight=\fR<n>
+.IP
+Set maximum BIP141 block weight (default: 3996000)
+.HP
+\fB\-blockmintxfee=\fR<amt>
+.IP
+Set lowest fee rate (in BTC/kvB) for transactions to be included in
+block creation. (default: 0.00001)
+.PP
+RPC server options:
+.HP
+\fB\-rest\fR
+.IP
+Accept public REST requests (default: 0)
+.HP
+\fB\-rpcallowip=\fR<ip>
+.IP
+Allow JSON\-RPC connections from specified source. Valid for <ip> are a
+single IP (e.g. 1.2.3.4), a network/netmask (e.g.
+1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This
+option can be specified multiple times
+.HP
+\fB\-rpcauth=\fR<userpw>
+.IP
+Username and HMAC\-SHA\-256 hashed password for JSON\-RPC connections. The
+field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A
+canonical python script is included in share/rpcauth. The client
+then connects normally using the
+rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This
+option can be specified multiple times
+.HP
+\fB\-rpcbind=\fR<addr>[:port]
+.IP
+Bind to given address to listen for JSON\-RPC connections. Do not expose
+the RPC server to untrusted networks such as the public internet!
+This option is ignored unless \fB\-rpcallowip\fR is also passed. Port is
+optional and overrides \fB\-rpcport\fR. Use [host]:port notation for
+IPv6. This option can be specified multiple times (default:
+127.0.0.1 and ::1 i.e., localhost)
+.HP
+\fB\-rpccookiefile=\fR<loc>
+.IP
+Location of the auth cookie. Relative paths will be prefixed by a
+net\-specific datadir location. (default: data dir)
+.HP
+\fB\-rpcpassword=\fR<pw>
+.IP
+Password for JSON\-RPC connections
+.HP
+\fB\-rpcport=\fR<port>
+.IP
+Listen for JSON\-RPC connections on <port> (default: 8332, testnet:
+18332, signet: 38332, regtest: 18443)
+.HP
+\fB\-rpcserialversion\fR
+.IP
+Sets the serialization of raw transaction or block hex returned in
+non\-verbose mode, non\-segwit(0) or segwit(1) (default: 1)
+.HP
+\fB\-rpcthreads=\fR<n>
+.IP
+Set the number of threads to service RPC calls (default: 4)
+.HP
+\fB\-rpcuser=\fR<user>
+.IP
+Username for JSON\-RPC connections
+.HP
+\fB\-rpcwhitelist=\fR<whitelist>
+.IP
+Set a whitelist to filter incoming RPC calls for a specific user. The
+field <whitelist> comes in the format: <USERNAME>:<rpc 1>,<rpc
+2>,...,<rpc n>. If multiple whitelists are set for a given user,
+they are set\-intersected. See \fB\-rpcwhitelistdefault\fR documentation
+for information on default whitelist behavior.
+.HP
+\fB\-rpcwhitelistdefault\fR
+.IP
+Sets default behavior for rpc whitelisting. Unless rpcwhitelistdefault
+is set to 0, if any \fB\-rpcwhitelist\fR is set, the rpc server acts as
+if all rpc users are subject to empty\-unless\-otherwise\-specified
+whitelists. If rpcwhitelistdefault is set to 1 and no
+\fB\-rpcwhitelist\fR is set, rpc server acts as if all rpc users are
+subject to empty whitelists.
+.HP
+\fB\-server\fR
+.IP
+Accept command line and JSON\-RPC commands
+.PP
+UI Options:
+.HP
+\fB\-choosedatadir\fR
+.IP
+Choose data directory on startup (default: 0)
+.HP
+\fB\-lang=\fR<lang>
+.IP
+Set language, for example "de_DE" (default: system locale)
+.HP
+\fB\-min\fR
+.IP
+Start minimized
+.HP
+\fB\-resetguisettings\fR
+.IP
+Reset all settings changed in the GUI
+.HP
+\fB\-splash\fR
+.IP
+Show splash screen on startup (default: 1)
+.SH COPYRIGHT
+Copyright (C) 2009-2022 The Bitcoin Core developers
-This is a placeholder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
+Please contribute if you find Bitcoin Core useful. Visit
+<https://bitcoincore.org/> for further information about the software.
+The source code is available from <https://github.com/bitcoin/bitcoin>.
+
+This is experimental software.
+Distributed under the MIT software license, see the accompanying file COPYING
+or <https://opensource.org/licenses/MIT> \ No newline at end of file
diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1
index 776bb46234..4b58804c07 100644
--- a/doc/man/bitcoin-tx.1
+++ b/doc/man/bitcoin-tx.1
@@ -1,5 +1,145 @@
-.TH BITCOIN-TX "1"
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
+.TH BITCOIN-TX "1" "December 2022" "bitcoin-tx v24.0.1" "User Commands"
.SH NAME
-bitcoin-tx \- manual page for bitcoin-tx
+bitcoin-tx \- manual page for bitcoin-tx v24.0.1
+.SH SYNOPSIS
+.B bitcoin-tx
+[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded bitcoin transaction\/\fR
+.br
+.B bitcoin-tx
+[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded bitcoin transaction\/\fR
+.SH DESCRIPTION
+Bitcoin Core bitcoin\-tx utility version v24.0.1
+.SH OPTIONS
+.HP
+\-?
+.IP
+Print this help message and exit
+.HP
+\fB\-create\fR
+.IP
+Create new, empty TX.
+.HP
+\fB\-json\fR
+.IP
+Select JSON output
+.HP
+\fB\-txid\fR
+.IP
+Output only the hex\-encoded transaction id of the resultant transaction.
+.HP
+\fB\-version\fR
+.IP
+Print version and exit
+.PP
+Debugging/Testing options:
+.PP
+Chain selection options:
+.HP
+\fB\-chain=\fR<chain>
+.IP
+Use the chain <chain> (default: main). Allowed values: main, test,
+signet, regtest
+.HP
+\fB\-signet\fR
+.IP
+Use the signet chain. Equivalent to \fB\-chain\fR=\fI\,signet\/\fR. Note that the network
+is defined by the \fB\-signetchallenge\fR parameter
+.HP
+\fB\-signetchallenge\fR
+.IP
+Blocks must satisfy the given script to be considered valid (only for
+signet networks; defaults to the global default signet test
+network challenge)
+.HP
+\fB\-signetseednode\fR
+.IP
+Specify a seed node for the signet network, in the hostname[:port]
+format, e.g. sig.net:1234 (may be used multiple times to specify
+multiple seed nodes; defaults to the global default signet test
+network seed node(s))
+.HP
+\fB\-testnet\fR
+.IP
+Use the test chain. Equivalent to \fB\-chain\fR=\fI\,test\/\fR.
+.PP
+Commands:
+.IP
+delin=N
+.IP
+Delete input N from TX
+.IP
+delout=N
+.IP
+Delete output N from TX
+.IP
+in=TXID:VOUT(:SEQUENCE_NUMBER)
+.IP
+Add input to TX
+.IP
+locktime=N
+.IP
+Set TX lock time to N
+.IP
+nversion=N
+.IP
+Set TX version to N
+.IP
+outaddr=VALUE:ADDRESS
+.IP
+Add address\-based output to TX
+.IP
+outdata=[VALUE:]DATA
+.IP
+Add data\-based output to TX
+.IP
+outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]
+.IP
+Add Pay To n\-of\-m Multi\-sig output to TX. n = REQUIRED, m = PUBKEYS.
+Optionally add the "W" flag to produce a
+pay\-to\-witness\-script\-hash output. Optionally add the "S" flag to
+wrap the output in a pay\-to\-script\-hash.
+.IP
+outpubkey=VALUE:PUBKEY[:FLAGS]
+.IP
+Add pay\-to\-pubkey output to TX. Optionally add the "W" flag to produce a
+pay\-to\-witness\-pubkey\-hash output. Optionally add the "S" flag to
+wrap the output in a pay\-to\-script\-hash.
+.IP
+outscript=VALUE:SCRIPT[:FLAGS]
+.IP
+Add raw script output to TX. Optionally add the "W" flag to produce a
+pay\-to\-witness\-script\-hash output. Optionally add the "S" flag to
+wrap the output in a pay\-to\-script\-hash.
+.IP
+replaceable(=N)
+.IP
+Set RBF opt\-in sequence number for input N (if not provided, opt\-in all
+available inputs)
+.IP
+sign=SIGHASH\-FLAGS
+.IP
+Add zero or more signatures to transaction. This command requires JSON
+registers:prevtxs=JSON object, privatekeys=JSON object. See
+signrawtransactionwithkey docs for format of sighash flags, JSON
+objects.
+.PP
+Register Commands:
+.IP
+load=NAME:FILENAME
+.IP
+Load JSON file FILENAME into register NAME
+.IP
+set=NAME:JSON\-STRING
+.IP
+Set register NAME to given JSON\-STRING
+.SH COPYRIGHT
+Copyright (C) 2009-2022 The Bitcoin Core developers
-This is a placeholder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
+Please contribute if you find Bitcoin Core useful. Visit
+<https://bitcoincore.org/> for further information about the software.
+The source code is available from <https://github.com/bitcoin/bitcoin>.
+
+This is experimental software.
+Distributed under the MIT software license, see the accompanying file COPYING
+or <https://opensource.org/licenses/MIT> \ No newline at end of file
diff --git a/doc/man/bitcoin-util.1 b/doc/man/bitcoin-util.1
index 5c733c6e21..50f98ae3ac 100644
--- a/doc/man/bitcoin-util.1
+++ b/doc/man/bitcoin-util.1
@@ -1,5 +1,65 @@
-.TH BITCOIN-UTIL "1"
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
+.TH BITCOIN-UTIL "1" "December 2022" "bitcoin-util v24.0.1" "User Commands"
.SH NAME
-bitcoin-util \- manual page for bitcoin-util
+bitcoin-util \- manual page for bitcoin-util v24.0.1
+.SH SYNOPSIS
+.B bitcoin-util
+[\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR
+.SH DESCRIPTION
+Bitcoin Core bitcoin\-util utility version v24.0.1
+.SH OPTIONS
+.HP
+\-?
+.IP
+Print this help message and exit
+.HP
+\fB\-version\fR
+.IP
+Print version and exit
+.PP
+Debugging/Testing options:
+.PP
+Chain selection options:
+.HP
+\fB\-chain=\fR<chain>
+.IP
+Use the chain <chain> (default: main). Allowed values: main, test,
+signet, regtest
+.HP
+\fB\-signet\fR
+.IP
+Use the signet chain. Equivalent to \fB\-chain\fR=\fI\,signet\/\fR. Note that the network
+is defined by the \fB\-signetchallenge\fR parameter
+.HP
+\fB\-signetchallenge\fR
+.IP
+Blocks must satisfy the given script to be considered valid (only for
+signet networks; defaults to the global default signet test
+network challenge)
+.HP
+\fB\-signetseednode\fR
+.IP
+Specify a seed node for the signet network, in the hostname[:port]
+format, e.g. sig.net:1234 (may be used multiple times to specify
+multiple seed nodes; defaults to the global default signet test
+network seed node(s))
+.HP
+\fB\-testnet\fR
+.IP
+Use the test chain. Equivalent to \fB\-chain\fR=\fI\,test\/\fR.
+.PP
+Commands:
+.IP
+grind
+.IP
+Perform proof of work on hex header string
+.SH COPYRIGHT
+Copyright (C) 2009-2022 The Bitcoin Core developers
-This is a placeholder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
+Please contribute if you find Bitcoin Core useful. Visit
+<https://bitcoincore.org/> for further information about the software.
+The source code is available from <https://github.com/bitcoin/bitcoin>.
+
+This is experimental software.
+Distributed under the MIT software license, see the accompanying file COPYING
+or <https://opensource.org/licenses/MIT> \ No newline at end of file
diff --git a/doc/man/bitcoin-wallet.1 b/doc/man/bitcoin-wallet.1
index 2da43dec66..212844aaf8 100644
--- a/doc/man/bitcoin-wallet.1
+++ b/doc/man/bitcoin-wallet.1
@@ -1,5 +1,121 @@
-.TH BITCOIN-WALLET "1"
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
+.TH BITCOIN-WALLET "1" "December 2022" "bitcoin-wallet v24.0.1" "User Commands"
.SH NAME
-bitcoin-wallet \- manual page for bitcoin-wallet
+bitcoin-wallet \- manual page for bitcoin-wallet v24.0.1
+.SH DESCRIPTION
+Bitcoin Core bitcoin\-wallet version v24.0.1
+.PP
+bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.
+By default bitcoin\-wallet will act on wallets in the default mainnet wallet directory in the datadir.
+To change the target wallet, use the \fB\-datadir\fR, \fB\-wallet\fR and \fB\-regtest\fR/\-signet/\-testnet arguments.
+.SS "Usage:"
+.IP
+bitcoin\-wallet [options] <command>
+.SH OPTIONS
+.HP
+\-?
+.IP
+Print this help message and exit
+.HP
+\fB\-datadir=\fR<dir>
+.IP
+Specify data directory
+.HP
+\fB\-descriptors\fR
+.IP
+Create descriptors wallet. Only for 'create'
+.HP
+\fB\-dumpfile=\fR<file name>
+.IP
+When used with 'dump', writes out the records to this file. When used
+with 'createfromdump', loads the records into a new wallet.
+.HP
+\fB\-format=\fR<format>
+.IP
+The format of the wallet file to create. Either "bdb" or "sqlite". Only
+used with 'createfromdump'
+.HP
+\fB\-legacy\fR
+.IP
+Create legacy wallet. Only for 'create'
+.HP
+\fB\-version\fR
+.IP
+Print version and exit
+.HP
+\fB\-wallet=\fR<wallet\-name>
+.IP
+Specify wallet name
+.PP
+Debugging/Testing options:
+.HP
+\fB\-debug=\fR<category>
+.IP
+Output debugging information (default: 0).
+.HP
+\fB\-printtoconsole\fR
+.IP
+Send trace/debug info to console (default: 1 when no \fB\-debug\fR is true, 0
+otherwise).
+.PP
+Chain selection options:
+.HP
+\fB\-chain=\fR<chain>
+.IP
+Use the chain <chain> (default: main). Allowed values: main, test,
+signet, regtest
+.HP
+\fB\-signet\fR
+.IP
+Use the signet chain. Equivalent to \fB\-chain\fR=\fI\,signet\/\fR. Note that the network
+is defined by the \fB\-signetchallenge\fR parameter
+.HP
+\fB\-signetchallenge\fR
+.IP
+Blocks must satisfy the given script to be considered valid (only for
+signet networks; defaults to the global default signet test
+network challenge)
+.HP
+\fB\-signetseednode\fR
+.IP
+Specify a seed node for the signet network, in the hostname[:port]
+format, e.g. sig.net:1234 (may be used multiple times to specify
+multiple seed nodes; defaults to the global default signet test
+network seed node(s))
+.HP
+\fB\-testnet\fR
+.IP
+Use the test chain. Equivalent to \fB\-chain\fR=\fI\,test\/\fR.
+.PP
+Commands:
+.IP
+create
+.IP
+Create new wallet file
+.IP
+createfromdump
+.IP
+Create new wallet file from dumped records
+.IP
+dump
+.IP
+Print out all of the wallet key\-value records
+.IP
+info
+.IP
+Get wallet info
+.IP
+salvage
+.IP
+Attempt to recover private keys from a corrupt wallet. Warning:
+\&'salvage' is experimental.
+.SH COPYRIGHT
+Copyright (C) 2009-2022 The Bitcoin Core developers
-This is a placeholder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
+Please contribute if you find Bitcoin Core useful. Visit
+<https://bitcoincore.org/> for further information about the software.
+The source code is available from <https://github.com/bitcoin/bitcoin>.
+
+This is experimental software.
+Distributed under the MIT software license, see the accompanying file COPYING
+or <https://opensource.org/licenses/MIT> \ No newline at end of file
diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1
index 2c88f74520..1ce173d92c 100644
--- a/doc/man/bitcoind.1
+++ b/doc/man/bitcoind.1
@@ -1,5 +1,796 @@
-.TH BITCOIND "1"
+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.2.
+.TH BITCOIND "1" "December 2022" "bitcoind v24.0.1" "User Commands"
.SH NAME
-bitcoind \- manual page for bitcoind
+bitcoind \- manual page for bitcoind v24.0.1
+.SH SYNOPSIS
+.B bitcoind
+[\fI\,options\/\fR] \fI\,Start Bitcoin Core\/\fR
+.SH DESCRIPTION
+Bitcoin Core version v24.0.1
+.SH OPTIONS
+.HP
+\-?
+.IP
+Print this help message and exit
+.HP
+\fB\-alertnotify=\fR<cmd>
+.IP
+Execute command when an alert is raised (%s in cmd is replaced by
+message)
+.HP
+\fB\-assumevalid=\fR<hex>
+.IP
+If this block is in the chain assume that it and its ancestors are valid
+and potentially skip their script verification (0 to verify all,
+default:
+00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd,
+testnet:
+0000000000000004877fa2d36316398528de4f347df2f8a96f76613a298ce060,
+signet:
+000000d1a0e224fa4679d2fb2187ba55431c284fa1b74cbc8cfda866fd4d2c09)
+.HP
+\fB\-blockfilterindex=\fR<type>
+.IP
+Maintain an index of compact filters by block (default: 0, values:
+basic). If <type> is not supplied or if <type> = 1, indexes for
+all known types are enabled.
+.HP
+\fB\-blocknotify=\fR<cmd>
+.IP
+Execute command when the best block changes (%s in cmd is replaced by
+block hash)
+.HP
+\fB\-blockreconstructionextratxn=\fR<n>
+.IP
+Extra transactions to keep in memory for compact block reconstructions
+(default: 100)
+.HP
+\fB\-blocksdir=\fR<dir>
+.IP
+Specify directory to hold blocks subdirectory for *.dat files (default:
+<datadir>)
+.HP
+\fB\-blocksonly\fR
+.IP
+Whether to reject transactions from network peers. Automatic broadcast
+and rebroadcast of any transactions from inbound peers is
+disabled, unless the peer has the 'forcerelay' permission. RPC
+transactions are not affected. (default: 0)
+.HP
+\fB\-coinstatsindex\fR
+.IP
+Maintain coinstats index used by the gettxoutsetinfo RPC (default: 0)
+.HP
+\fB\-conf=\fR<file>
+.IP
+Specify path to read\-only configuration file. Relative paths will be
+prefixed by datadir location (only useable from command line, not
+configuration file) (default: bitcoin.conf)
+.HP
+\fB\-daemon\fR
+.IP
+Run in the background as a daemon and accept commands (default: 0)
+.HP
+\fB\-daemonwait\fR
+.IP
+Wait for initialization to be finished before exiting. This implies
+\fB\-daemon\fR (default: 0)
+.HP
+\fB\-datadir=\fR<dir>
+.IP
+Specify data directory
+.HP
+\fB\-dbcache=\fR<n>
+.IP
+Maximum database cache size <n> MiB (4 to 16384, default: 450). In
+addition, unused mempool memory is shared for this cache (see
+\fB\-maxmempool\fR).
+.HP
+\fB\-debuglogfile=\fR<file>
+.IP
+Specify location of debug log file. Relative paths will be prefixed by a
+net\-specific datadir location. (\fB\-nodebuglogfile\fR to disable;
+default: debug.log)
+.HP
+\fB\-includeconf=\fR<file>
+.IP
+Specify additional configuration file, relative to the \fB\-datadir\fR path
+(only useable from configuration file, not command line)
+.HP
+\fB\-loadblock=\fR<file>
+.IP
+Imports blocks from external file on startup
+.HP
+\fB\-maxmempool=\fR<n>
+.IP
+Keep the transaction memory pool below <n> megabytes (default: 300)
+.HP
+\fB\-maxorphantx=\fR<n>
+.IP
+Keep at most <n> unconnectable transactions in memory (default: 100)
+.HP
+\fB\-mempoolexpiry=\fR<n>
+.IP
+Do not keep transactions in the mempool longer than <n> hours (default:
+336)
+.HP
+\fB\-par=\fR<n>
+.IP
+Set the number of script verification threads (\fB\-10\fR to 15, 0 = auto, <0 =
+leave that many cores free, default: 0)
+.HP
+\fB\-persistmempool\fR
+.IP
+Whether to save the mempool on shutdown and load on restart (default: 1)
+.HP
+\fB\-pid=\fR<file>
+.IP
+Specify pid file. Relative paths will be prefixed by a net\-specific
+datadir location. (default: bitcoind.pid)
+.HP
+\fB\-prune=\fR<n>
+.IP
+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 \fB\-txindex\fR. Warning: Reverting this setting
+requires re\-downloading the entire blockchain. (default: 0 =
+disable pruning blocks, 1 = allow manual pruning via RPC, >=550 =
+automatically prune block files to stay under the specified
+target size in MiB)
+.HP
+\fB\-reindex\fR
+.IP
+Rebuild chain state and block index from the blk*.dat files on disk.
+This will also rebuild active optional indexes.
+.HP
+\fB\-reindex\-chainstate\fR
+.IP
+Rebuild chain state from the currently indexed blocks. When in pruning
+mode or if blocks on disk might be corrupted, use full \fB\-reindex\fR
+instead. Deactivate all optional indexes before running this.
+.HP
+\fB\-sandbox=\fR<mode>
+.IP
+Use the experimental syscall sandbox in the specified mode
+(\fB\-sandbox\fR=\fI\,log\-and\-abort\/\fR or \fB\-sandbox\fR=\fI\,abort\/\fR). Allow only expected
+syscalls to be used by bitcoind. Note that this is an
+experimental new feature that may cause bitcoind to exit or crash
+unexpectedly: use with caution. In the "log\-and\-abort" mode the
+invocation of an unexpected syscall results in a debug handler
+being invoked which will log the incident and terminate the
+program (without executing the unexpected syscall). In the
+"abort" mode the invocation of an unexpected syscall results in
+the entire process being killed immediately by the kernel without
+executing the unexpected syscall.
+.HP
+\fB\-settings=\fR<file>
+.IP
+Specify path to dynamic settings data file. Can be disabled with
+\fB\-nosettings\fR. File is written at runtime and not meant to be
+edited by users (use bitcoin.conf instead for custom settings).
+Relative paths will be prefixed by datadir location. (default:
+settings.json)
+.HP
+\fB\-startupnotify=\fR<cmd>
+.IP
+Execute command on startup.
+.HP
+\fB\-sysperms\fR
+.IP
+Create new files with system default permissions, instead of umask 077
+(only effective with disabled wallet functionality)
+.HP
+\fB\-txindex\fR
+.IP
+Maintain a full transaction index, used by the getrawtransaction rpc
+call (default: 0)
+.HP
+\fB\-version\fR
+.IP
+Print version and exit
+.PP
+Connection options:
+.HP
+\fB\-addnode=\fR<ip>
+.IP
+Add a node to connect to and attempt to keep the connection open (see
+the addnode RPC help for more info). This option can be specified
+multiple times to add multiple nodes; connections are limited to
+8 at a time and are counted separately from the \fB\-maxconnections\fR
+limit.
+.HP
+\fB\-asmap=\fR<file>
+.IP
+Specify asn mapping used for bucketing of the peers (default:
+ip_asn.map). Relative paths will be prefixed by the net\-specific
+datadir location.
+.HP
+\fB\-bantime=\fR<n>
+.IP
+Default duration (in seconds) of manually configured bans (default:
+86400)
+.HP
+\fB\-bind=\fR<addr>[:<port>][=onion]
+.IP
+Bind to given address and always listen on it (default: 0.0.0.0). Use
+[host]:port notation for IPv6. Append =onion to tag any incoming
+connections to that address and port as incoming Tor connections
+(default: 127.0.0.1:8334=onion, testnet: 127.0.0.1:18334=onion,
+signet: 127.0.0.1:38334=onion, regtest: 127.0.0.1:18445=onion)
+.HP
+\fB\-cjdnsreachable\fR
+.IP
+If set, then this host is configured for CJDNS (connecting to fc00::/8
+addresses would lead us to the CJDNS network, see doc/cjdns.md)
+(default: 0)
+.HP
+\fB\-connect=\fR<ip>
+.IP
+Connect only to the specified node; \fB\-noconnect\fR disables automatic
+connections (the rules for this peer are the same as for
+\fB\-addnode\fR). This option can be specified multiple times to connect
+to multiple nodes.
+.HP
+\fB\-discover\fR
+.IP
+Discover own IP addresses (default: 1 when listening and no \fB\-externalip\fR
+or \fB\-proxy\fR)
+.HP
+\fB\-dns\fR
+.IP
+Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (default: 1)
+.HP
+\fB\-dnsseed\fR
+.IP
+Query for peer addresses via DNS lookup, if low on addresses (default: 1
+unless \fB\-connect\fR used)
+.HP
+\fB\-externalip=\fR<ip>
+.IP
+Specify your own public address
+.HP
+\fB\-fixedseeds\fR
+.IP
+Allow fixed seeds if DNS seeds don't provide peers (default: 1)
+.HP
+\fB\-forcednsseed\fR
+.IP
+Always query for peer addresses via DNS lookup (default: 0)
+.HP
+\fB\-i2pacceptincoming\fR
+.IP
+If set and \fB\-i2psam\fR is also set then incoming I2P connections are
+accepted via the SAM proxy. If this is not set but \fB\-i2psam\fR is set
+then only outgoing connections will be made to the I2P network.
+Ignored if \fB\-i2psam\fR is not set. Listening for incoming I2P
+connections is done through the SAM proxy, not by binding to a
+local address and port (default: 1)
+.HP
+\fB\-i2psam=\fR<ip:port>
+.IP
+I2P SAM proxy to reach I2P peers and accept I2P connections (default:
+none)
+.HP
+\fB\-listen\fR
+.IP
+Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR)
+.HP
+\fB\-listenonion\fR
+.IP
+Automatically create Tor onion service (default: 1)
+.HP
+\fB\-maxconnections=\fR<n>
+.IP
+Maintain at most <n> connections to peers (default: 125). This limit
+does not apply to connections manually added via \fB\-addnode\fR or the
+addnode RPC, which have a separate limit of 8.
+.HP
+\fB\-maxreceivebuffer=\fR<n>
+.IP
+Maximum per\-connection receive buffer, <n>*1000 bytes (default: 5000)
+.HP
+\fB\-maxsendbuffer=\fR<n>
+.IP
+Maximum per\-connection send buffer, <n>*1000 bytes (default: 1000)
+.HP
+\fB\-maxtimeadjustment\fR
+.IP
+Maximum allowed median peer time offset adjustment. Local perspective of
+time may be influenced by outbound peers forward or backward by
+this amount (default: 4200 seconds).
+.HP
+\fB\-maxuploadtarget=\fR<n>
+.IP
+Tries to keep outbound traffic under the given target per 24h. Limit
+does not apply to peers with 'download' permission or blocks
+created within past week. 0 = no limit (default: 0M). Optional
+suffix units [k|K|m|M|g|G|t|T] (default: M). Lowercase is 1000
+base while uppercase is 1024 base
+.HP
+\fB\-natpmp\fR
+.IP
+Use NAT\-PMP to map the listening port (default: 0)
+.HP
+\fB\-networkactive\fR
+.IP
+Enable all P2P network activity (default: 1). Can be changed by the
+setnetworkactive RPC command
+.HP
+\fB\-onion=\fR<ip:port>
+.IP
+Use separate SOCKS5 proxy to reach peers via Tor onion services, set
+\fB\-noonion\fR to disable (default: \fB\-proxy\fR)
+.HP
+\fB\-onlynet=\fR<net>
+.IP
+Make automatic outbound connections only to network <net> (ipv4, ipv6,
+onion, i2p, cjdns). Inbound and manual connections are not
+affected by this option. It can be specified multiple times to
+allow multiple networks.
+.HP
+\fB\-peerblockfilters\fR
+.IP
+Serve compact block filters to peers per BIP 157 (default: 0)
+.HP
+\fB\-peerbloomfilters\fR
+.IP
+Support filtering of blocks and transaction with bloom filters (default:
+0)
+.HP
+\fB\-port=\fR<port>
+.IP
+Listen for connections on <port>. Nodes not using the default ports
+(default: 8333, testnet: 18333, signet: 38333, regtest: 18444)
+are unlikely to get incoming connections. Not relevant for I2P
+(see doc/i2p.md).
+.HP
+\fB\-proxy=\fR<ip:port>
+.IP
+Connect through SOCKS5 proxy, set \fB\-noproxy\fR to disable (default:
+disabled)
+.HP
+\fB\-proxyrandomize\fR
+.IP
+Randomize credentials for every proxy connection. This enables Tor
+stream isolation (default: 1)
+.HP
+\fB\-seednode=\fR<ip>
+.IP
+Connect to a node to retrieve peer addresses, and disconnect. This
+option can be specified multiple times to connect to multiple
+nodes.
+.HP
+\fB\-timeout=\fR<n>
+.IP
+Specify socket connection timeout in milliseconds. If an initial attempt
+to connect is unsuccessful after this amount of time, drop it
+(minimum: 1, default: 5000)
+.HP
+\fB\-torcontrol=\fR<ip>:<port>
+.IP
+Tor control port to use if onion listening enabled (default:
+127.0.0.1:9051)
+.HP
+\fB\-torpassword=\fR<pass>
+.IP
+Tor control port password (default: empty)
+.HP
+\fB\-upnp\fR
+.IP
+Use UPnP to map the listening port (default: 0)
+.HP
+\fB\-whitebind=\fR<[permissions@]addr>
+.IP
+Bind to the given address and add permission flags to the peers
+connecting to it. Use [host]:port notation for IPv6. Allowed
+permissions: bloomfilter (allow requesting BIP37 filtered blocks
+and transactions), noban (do not ban for misbehavior; implies
+download), forcerelay (relay transactions that are already in the
+mempool; implies relay), relay (relay even in \fB\-blocksonly\fR mode,
+and unlimited transaction announcements), mempool (allow
+requesting BIP35 mempool contents), download (allow getheaders
+during IBD, no disconnect after maxuploadtarget limit), addr
+(responses to GETADDR avoid hitting the cache and contain random
+records with the most up\-to\-date info). Specify multiple
+permissions separated by commas (default:
+download,noban,mempool,relay). Can be specified multiple times.
+.HP
+\fB\-whitelist=\fR<[permissions@]IP address or network>
+.IP
+Add permission flags to the peers connecting from the given IP address
+(e.g. 1.2.3.4) or CIDR\-notated network (e.g. 1.2.3.0/24). Uses
+the same permissions as \fB\-whitebind\fR. Can be specified multiple
+times.
+.PP
+Wallet options:
+.HP
+\fB\-addresstype\fR
+.IP
+What type of addresses to use ("legacy", "p2sh\-segwit", "bech32", or
+"bech32m", default: "bech32")
+.HP
+\fB\-avoidpartialspends\fR
+.IP
+Group outputs by address, selecting many (possibly all) or none, instead
+of selecting on a per\-output basis. Privacy is improved as
+addresses are mostly swept with fewer transactions and outputs
+are aggregated in clean change addresses. It may result in higher
+fees due to less optimal coin selection caused by this added
+limitation and possibly a larger\-than\-necessary number of inputs
+being used. Always enabled for wallets with "avoid_reuse"
+enabled, otherwise default: 0.
+.HP
+\fB\-changetype\fR
+.IP
+What type of change to use ("legacy", "p2sh\-segwit", "bech32", or
+"bech32m"). Default is "legacy" when \fB\-addresstype\fR=\fI\,legacy\/\fR, else it
+is an implementation detail.
+.HP
+\fB\-consolidatefeerate=\fR<amt>
+.IP
+The maximum feerate (in BTC/kvB) at which transaction building may use
+more inputs than strictly necessary so that the wallet's UTXO
+pool can be reduced (default: 0.0001).
+.HP
+\fB\-disablewallet\fR
+.IP
+Do not load the wallet and disable wallet RPC calls
+.HP
+\fB\-discardfee=\fR<amt>
+.IP
+The fee rate (in BTC/kvB) that indicates your tolerance for discarding
+change by adding it to the fee (default: 0.0001). Note: An output
+is discarded if it is dust at this rate, but we will always
+discard up to the dust relay fee and a discard fee above that is
+limited by the fee estimate for the longest target
+.HP
+\fB\-fallbackfee=\fR<amt>
+.IP
+A fee rate (in BTC/kvB) that will be used when fee estimation has
+insufficient data. 0 to entirely disable the fallbackfee feature.
+(default: 0.00)
+.HP
+\fB\-keypool=\fR<n>
+.IP
+Set key pool size to <n> (default: 1000). Warning: Smaller sizes may
+increase the risk of losing funds when restoring from an old
+backup, if none of the addresses in the original keypool have
+been used.
+.HP
+\fB\-maxapsfee=\fR<n>
+.IP
+Spend up to this amount in additional (absolute) fees (in BTC) if it
+allows the use of partial spend avoidance (default: 0.00)
+.HP
+\fB\-mintxfee=\fR<amt>
+.IP
+Fee rates (in BTC/kvB) smaller than this are considered zero fee for
+transaction creation (default: 0.00001)
+.HP
+\fB\-paytxfee=\fR<amt>
+.IP
+Fee rate (in BTC/kvB) to add to transactions you send (default: 0.00)
+.HP
+\fB\-signer=\fR<cmd>
+.IP
+External signing tool, see doc/external\-signer.md
+.HP
+\fB\-spendzeroconfchange\fR
+.IP
+Spend unconfirmed change when sending transactions (default: 1)
+.HP
+\fB\-txconfirmtarget=\fR<n>
+.IP
+If paytxfee is not set, include enough fee so transactions begin
+confirmation on average within n blocks (default: 6)
+.HP
+\fB\-wallet=\fR<path>
+.IP
+Specify wallet path to load at startup. Can be used multiple times to
+load multiple wallets. Path is to a directory containing wallet
+data and log files. If the path is not absolute, it is
+interpreted relative to <walletdir>. This only loads existing
+wallets and does not create new ones. For backwards compatibility
+this also accepts names of existing top\-level data files in
+<walletdir>.
+.HP
+\fB\-walletbroadcast\fR
+.IP
+Make the wallet broadcast transactions (default: 1)
+.HP
+\fB\-walletdir=\fR<dir>
+.IP
+Specify directory to hold wallets (default: <datadir>/wallets if it
+exists, otherwise <datadir>)
+.HP
+\fB\-walletnotify=\fR<cmd>
+.IP
+Execute command when a wallet transaction changes. %s in cmd is replaced
+by TxID, %w is replaced by wallet name, %b is replaced by the
+hash of the block including the transaction (set to 'unconfirmed'
+if the transaction is not included) and %h is replaced by the
+block height (\fB\-1\fR if not included). %w is not currently
+implemented on windows. On systems where %w is supported, it
+should NOT be quoted because this would break shell escaping used
+to invoke the command.
+.HP
+\fB\-walletrbf\fR
+.IP
+Send transactions with full\-RBF opt\-in enabled (RPC only, default: 1)
+.PP
+ZeroMQ notification options:
+.HP
+\fB\-zmqpubhashblock=\fR<address>
+.IP
+Enable publish hash block in <address>
+.HP
+\fB\-zmqpubhashblockhwm=\fR<n>
+.IP
+Set publish hash block outbound message high water mark (default: 1000)
+.HP
+\fB\-zmqpubhashtx=\fR<address>
+.IP
+Enable publish hash transaction in <address>
+.HP
+\fB\-zmqpubhashtxhwm=\fR<n>
+.IP
+Set publish hash transaction outbound message high water mark (default:
+1000)
+.HP
+\fB\-zmqpubrawblock=\fR<address>
+.IP
+Enable publish raw block in <address>
+.HP
+\fB\-zmqpubrawblockhwm=\fR<n>
+.IP
+Set publish raw block outbound message high water mark (default: 1000)
+.HP
+\fB\-zmqpubrawtx=\fR<address>
+.IP
+Enable publish raw transaction in <address>
+.HP
+\fB\-zmqpubrawtxhwm=\fR<n>
+.IP
+Set publish raw transaction outbound message high water mark (default:
+1000)
+.HP
+\fB\-zmqpubsequence=\fR<address>
+.IP
+Enable publish hash block and tx sequence in <address>
+.HP
+\fB\-zmqpubsequencehwm=\fR<n>
+.IP
+Set publish hash sequence message high water mark (default: 1000)
+.PP
+Debugging/Testing options:
+.HP
+\fB\-debug=\fR<category>
+.IP
+Output debug and trace logging (default: \fB\-nodebug\fR, supplying <category>
+is optional). If <category> is not supplied or if <category> = 1,
+output all debug and trace logging. <category> can be: addrman,
+bench, blockstorage, cmpctblock, coindb, estimatefee, http, i2p,
+ipc, leveldb, libevent, mempool, mempoolrej, net, proxy, prune,
+qt, rand, reindex, rpc, selectcoins, tor, util, validation,
+walletdb, zmq. This option can be specified multiple times to
+output multiple categories.
+.HP
+\fB\-debugexclude=\fR<category>
+.IP
+Exclude debug and trace logging for a category. Can be used in
+conjunction with \fB\-debug\fR=\fI\,1\/\fR to output debug and trace logging for
+all categories except the specified category. This option can be
+specified multiple times to exclude multiple categories.
+.HP
+\fB\-help\-debug\fR
+.IP
+Print help message with debugging options and exit
+.HP
+\fB\-logips\fR
+.IP
+Include IP addresses in debug output (default: 0)
+.HP
+\fB\-logsourcelocations\fR
+.IP
+Prepend debug output with name of the originating source location
+(source file, line number and function name) (default: 0)
+.HP
+\fB\-logthreadnames\fR
+.IP
+Prepend debug output with name of the originating thread (only available
+on platforms supporting thread_local) (default: 0)
+.HP
+\fB\-logtimestamps\fR
+.IP
+Prepend debug output with timestamp (default: 1)
+.HP
+\fB\-maxtxfee=\fR<amt>
+.IP
+Maximum total fees (in BTC) to use in a single wallet transaction;
+setting this too low may abort large transactions (default: 0.10)
+.HP
+\fB\-printtoconsole\fR
+.IP
+Send trace/debug info to console (default: 1 when no \fB\-daemon\fR. To disable
+logging to file, set \fB\-nodebuglogfile\fR)
+.HP
+\fB\-shrinkdebugfile\fR
+.IP
+Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR)
+.HP
+\fB\-uacomment=\fR<cmt>
+.IP
+Append comment to the user agent string
+.PP
+Chain selection options:
+.HP
+\fB\-chain=\fR<chain>
+.IP
+Use the chain <chain> (default: main). Allowed values: main, test,
+signet, regtest
+.HP
+\fB\-signet\fR
+.IP
+Use the signet chain. Equivalent to \fB\-chain\fR=\fI\,signet\/\fR. Note that the network
+is defined by the \fB\-signetchallenge\fR parameter
+.HP
+\fB\-signetchallenge\fR
+.IP
+Blocks must satisfy the given script to be considered valid (only for
+signet networks; defaults to the global default signet test
+network challenge)
+.HP
+\fB\-signetseednode\fR
+.IP
+Specify a seed node for the signet network, in the hostname[:port]
+format, e.g. sig.net:1234 (may be used multiple times to specify
+multiple seed nodes; defaults to the global default signet test
+network seed node(s))
+.HP
+\fB\-testnet\fR
+.IP
+Use the test chain. Equivalent to \fB\-chain\fR=\fI\,test\/\fR.
+.PP
+Node relay options:
+.HP
+\fB\-bytespersigop\fR
+.IP
+Equivalent bytes per sigop in transactions for relay and mining
+(default: 20)
+.HP
+\fB\-datacarrier\fR
+.IP
+Relay and mine data carrier transactions (default: 1)
+.HP
+\fB\-datacarriersize\fR
+.IP
+Maximum size of data in data carrier transactions we relay and mine
+(default: 83)
+.HP
+\fB\-mempoolfullrbf\fR
+.IP
+Accept transaction replace\-by\-fee without requiring replaceability
+signaling (default: 0)
+.HP
+\fB\-minrelaytxfee=\fR<amt>
+.IP
+Fees (in BTC/kvB) smaller than this are considered zero fee for
+relaying, mining and transaction creation (default: 0.00001)
+.HP
+\fB\-permitbaremultisig\fR
+.IP
+Relay non\-P2SH multisig (default: 1)
+.HP
+\fB\-whitelistforcerelay\fR
+.IP
+Add 'forcerelay' permission to whitelisted inbound peers with default
+permissions. This will relay transactions even if the
+transactions were already in the mempool. (default: 0)
+.HP
+\fB\-whitelistrelay\fR
+.IP
+Add 'relay' permission to whitelisted inbound peers with default
+permissions. This will accept relayed transactions even when not
+relaying transactions (default: 1)
+.PP
+Block creation options:
+.HP
+\fB\-blockmaxweight=\fR<n>
+.IP
+Set maximum BIP141 block weight (default: 3996000)
+.HP
+\fB\-blockmintxfee=\fR<amt>
+.IP
+Set lowest fee rate (in BTC/kvB) for transactions to be included in
+block creation. (default: 0.00001)
+.PP
+RPC server options:
+.HP
+\fB\-rest\fR
+.IP
+Accept public REST requests (default: 0)
+.HP
+\fB\-rpcallowip=\fR<ip>
+.IP
+Allow JSON\-RPC connections from specified source. Valid for <ip> are a
+single IP (e.g. 1.2.3.4), a network/netmask (e.g.
+1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This
+option can be specified multiple times
+.HP
+\fB\-rpcauth=\fR<userpw>
+.IP
+Username and HMAC\-SHA\-256 hashed password for JSON\-RPC connections. The
+field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A
+canonical python script is included in share/rpcauth. The client
+then connects normally using the
+rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This
+option can be specified multiple times
+.HP
+\fB\-rpcbind=\fR<addr>[:port]
+.IP
+Bind to given address to listen for JSON\-RPC connections. Do not expose
+the RPC server to untrusted networks such as the public internet!
+This option is ignored unless \fB\-rpcallowip\fR is also passed. Port is
+optional and overrides \fB\-rpcport\fR. Use [host]:port notation for
+IPv6. This option can be specified multiple times (default:
+127.0.0.1 and ::1 i.e., localhost)
+.HP
+\fB\-rpccookiefile=\fR<loc>
+.IP
+Location of the auth cookie. Relative paths will be prefixed by a
+net\-specific datadir location. (default: data dir)
+.HP
+\fB\-rpcpassword=\fR<pw>
+.IP
+Password for JSON\-RPC connections
+.HP
+\fB\-rpcport=\fR<port>
+.IP
+Listen for JSON\-RPC connections on <port> (default: 8332, testnet:
+18332, signet: 38332, regtest: 18443)
+.HP
+\fB\-rpcserialversion\fR
+.IP
+Sets the serialization of raw transaction or block hex returned in
+non\-verbose mode, non\-segwit(0) or segwit(1) (default: 1)
+.HP
+\fB\-rpcthreads=\fR<n>
+.IP
+Set the number of threads to service RPC calls (default: 4)
+.HP
+\fB\-rpcuser=\fR<user>
+.IP
+Username for JSON\-RPC connections
+.HP
+\fB\-rpcwhitelist=\fR<whitelist>
+.IP
+Set a whitelist to filter incoming RPC calls for a specific user. The
+field <whitelist> comes in the format: <USERNAME>:<rpc 1>,<rpc
+2>,...,<rpc n>. If multiple whitelists are set for a given user,
+they are set\-intersected. See \fB\-rpcwhitelistdefault\fR documentation
+for information on default whitelist behavior.
+.HP
+\fB\-rpcwhitelistdefault\fR
+.IP
+Sets default behavior for rpc whitelisting. Unless rpcwhitelistdefault
+is set to 0, if any \fB\-rpcwhitelist\fR is set, the rpc server acts as
+if all rpc users are subject to empty\-unless\-otherwise\-specified
+whitelists. If rpcwhitelistdefault is set to 1 and no
+\fB\-rpcwhitelist\fR is set, rpc server acts as if all rpc users are
+subject to empty whitelists.
+.HP
+\fB\-server\fR
+.IP
+Accept command line and JSON\-RPC commands
+.SH COPYRIGHT
+Copyright (C) 2009-2022 The Bitcoin Core developers
-This is a placeholder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
+Please contribute if you find Bitcoin Core useful. Visit
+<https://bitcoincore.org/> for further information about the software.
+The source code is available from <https://github.com/bitcoin/bitcoin>.
+
+This is experimental software.
+Distributed under the MIT software license, see the accompanying file COPYING
+or <https://opensource.org/licenses/MIT> \ No newline at end of file
diff --git a/doc/managing-wallets.md b/doc/managing-wallets.md
index 6c1e13c503..366d7ec54b 100644
--- a/doc/managing-wallets.md
+++ b/doc/managing-wallets.md
@@ -120,4 +120,29 @@ After that, `getwalletinfo` can be used to check if the wallet has been fully re
$ bitcoin-cli -rpcwallet="restored-wallet" getwalletinfo
```
-The restored wallet can also be loaded in the GUI via `File` ->`Open wallet`. \ No newline at end of file
+The restored wallet can also be loaded in the GUI via `File` ->`Open wallet`.
+
+## Migrating Legacy Wallets to Descriptor Wallets
+
+Legacy wallets (traditional non-descriptor wallets) can be migrated to become Descriptor wallets
+through the use of the `migratewallet` RPC. Migrated wallets will have all of their addresses and private keys added to
+a newly created Descriptor wallet that has the same name as the original wallet. Because Descriptor
+wallets do not support having private keys and watch-only scripts, there may be up to two
+additional wallets created after migration. In addition to a descriptor wallet of the same name,
+there may also be a wallet named `<name>_watchonly` and `<name>_solvables`. `<name>_watchonly`
+contains all of the watchonly scripts. `<name>_solvables` contains any scripts which the wallet
+knows but is not watching the corresponding P2(W)SH scripts.
+
+Migrated wallets will also generate new addresses differently. While the same BIP 32 seed will be
+used, the BIP 44, 49, 84, and 86 standard derivation paths will be used. After migrating, a new
+backup of the wallet(s) will need to be created.
+
+Given that there is an extremely large number of possible configurations for the scripts that
+Legacy wallets can know about, be watching for, and be able to sign for, `migratewallet` only
+makes a best effort attempt to capture all of these things into Descriptor wallets. There may be
+unforeseen configurations which result in some scripts being excluded. If a migration fails
+unexpectedly or otherwise misses any scripts, please create an issue on GitHub. A backup of the
+original wallet can be found in the wallet directory with the name `<name>-<timestamp>.legacy.bak`.
+
+The backup can be restored using the `restorewallet` command as discussed in the
+[Restoring the Wallet From a Backup](#16-restoring-the-wallet-from-a-backup) section
diff --git a/doc/policy/README.md b/doc/policy/README.md
index 6e8686365d..27536407e7 100644
--- a/doc/policy/README.md
+++ b/doc/policy/README.md
@@ -3,7 +3,7 @@
**Policy** (Mempool or Transaction Relay Policy) is the node's set of validation rules, in addition
to consensus, enforced for unconfirmed transactions before submitting them to the mempool. These
rules are local to the node and configurable (e.g. `-minrelaytxfee`, `-limitancestorsize`,
-`-incrementalRelayFee`). Policy may include restrictions on the transaction itself, the transaction
+`-incrementalrelayfee`). Policy may include restrictions on the transaction itself, the transaction
in relation to the current chain tip, and the transaction in relation to the node's mempool
contents. Policy is *not* applied to transactions in blocks.
diff --git a/doc/policy/mempool-replacements.md b/doc/policy/mempool-replacements.md
index 18f08daf88..b3c4239b73 100644
--- a/doc/policy/mempool-replacements.md
+++ b/doc/policy/mempool-replacements.md
@@ -15,6 +15,8 @@ other consensus and policy rules, each of the following conditions are met:
*Rationale*: See [BIP125
explanation](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki#motivation).
+ Use the (`-mempoolfullrbf`) configuration option to allow transaction replacement without enforcement of the
+ opt-in signaling rule.
2. The replacement transaction only include an unconfirmed input if that input was included in
one of the directly conflicting transactions. An unconfirmed input spends an output from a
@@ -69,8 +71,11 @@ This set of rules is similar but distinct from BIP125.
Bitcoin Core implementation.
* The incremental relay feerate used to calculate the required additional fees is distinct from
- `minRelayTxFee` and configurable using `-incrementalrelayfee`
+ `-minrelaytxfee` and configurable using `-incrementalrelayfee`
([PR #9380](https://github.com/bitcoin/bitcoin/pull/9380)).
* RBF enabled by default in the wallet GUI as of **v0.18.1** ([PR
#11605](https://github.com/bitcoin/bitcoin/pull/11605)).
+
+* Full replace-by-fee enabled as a configurable mempool policy as of **v24.0** ([PR
+ #25353](https://github.com/bitcoin/bitcoin/pull/25353)).
diff --git a/doc/policy/packages.md b/doc/policy/packages.md
index f2a3d6517e..274854ddf9 100644
--- a/doc/policy/packages.md
+++ b/doc/policy/packages.md
@@ -33,7 +33,7 @@ The following rules are enforced for all packages:
* Packages cannot have conflicting transactions, i.e. no two transactions in a package can spend
the same inputs. Packages cannot have duplicate transactions. (#20833)
-* No transaction in a package can conflict with a mempool transaction. BIP125 Replace By Fee is
+* No transaction in a package can conflict with a mempool transaction. Replace By Fee is
currently disabled for packages. (#20833)
- Package RBF may be enabled in the future.
@@ -81,7 +81,7 @@ If any transactions in the package are already in the mempool, they are not subm
("deduplicated") and are thus excluded from this calculation.
To meet the two feerate requirements of a mempool, i.e., the pre-configured minimum relay feerate
-(`minRelayTxFee`) and the dynamic mempool minimum feerate, the total package feerate is used instead
+(`-minrelaytxfee`) and the dynamic mempool minimum feerate, the total package feerate is used instead
of the individual feerate. The individual transactions are allowed to be below the feerate
requirements if the package meets the feerate requirements. For example, the parent(s) in the
package can pay no fees but be paid for by the child.
diff --git a/doc/release-notes-15936.md b/doc/release-notes-15936.md
deleted file mode 100644
index 90c0413b9a..0000000000
--- a/doc/release-notes-15936.md
+++ /dev/null
@@ -1,15 +0,0 @@
-GUI changes
------------
-
-Configuration changes made in the bitcoin GUI (such as the pruning setting,
-proxy settings, UPNP preferences) are now saved to `<datadir>/settings.json`
-file rather than to the Qt settings backend (windows registry or unix desktop
-config files), so these settings will now apply to bitcoind, instead of being
-ignored.
-
-Also, the interaction between GUI settings and `bitcoin.conf` settings is
-simplified. Settings from `bitcoin.conf` are now displayed normally in the GUI
-settings dialog, instead of in a separate warning message ("Options set in this
-dialog are overridden by the configuration file: -setting=value"). And these
-settings can now be edited because `settings.json` values take precedence over
-`bitcoin.conf` values.
diff --git a/doc/release-notes-24098.md b/doc/release-notes-24098.md
deleted file mode 100644
index 79e047e9a5..0000000000
--- a/doc/release-notes-24098.md
+++ /dev/null
@@ -1,22 +0,0 @@
-Notable changes
-===============
-
-Updated REST APIs
------------------
-
-- The `/headers/` and `/blockfilterheaders/` endpoints have been updated to use
- a query parameter instead of path parameter to specify the result count. The
- count parameter is now optional, and defaults to 5 for both endpoints. The old
- endpoints are still functional, and have no documented behaviour change.
-
- For `/headers`, use
- `GET /rest/headers/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>`
- instead of
- `GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated)
-
- For `/blockfilterheaders/`, use
- `GET /rest/blockfilterheaders/<FILTERTYPE>/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>`
- instead of
- `GET /rest/blockfilterheaders/<FILTERTYPE>/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated)
-
- (#24098)
diff --git a/doc/release-notes-24118.md b/doc/release-notes-24118.md
deleted file mode 100644
index 16f23c7d00..0000000000
--- a/doc/release-notes-24118.md
+++ /dev/null
@@ -1,10 +0,0 @@
-New RPCs
---------
-
-- The `sendall` RPC spends specific UTXOs to one or more recipients
- without creating change. By default, the `sendall` RPC will spend
- every UTXO in the wallet. `sendall` is useful to empty wallets or to
- create a changeless payment from select UTXOs. When creating a payment
- from a specific amount for which the recipient incurs the transaction
- fee, continue to use the `subtractfeefromamount` option via the
- `send`, `sendtoaddress`, or `sendmany` RPCs. (#24118)
diff --git a/doc/release-notes-24198.md b/doc/release-notes-24198.md
deleted file mode 100644
index e41b2a8e26..0000000000
--- a/doc/release-notes-24198.md
+++ /dev/null
@@ -1,6 +0,0 @@
-Updated RPCs
-------------
-
-- The `listtransactions`, `gettransaction`, and `listsinceblock`
- RPC methods now include a wtxid field (hash of serialized transaction,
- including witness data) for each transaction. \ No newline at end of file
diff --git a/doc/release-notes-24494.md b/doc/release-notes-24494.md
deleted file mode 100644
index afbb926433..0000000000
--- a/doc/release-notes-24494.md
+++ /dev/null
@@ -1,2 +0,0 @@
-To help prevent fingerprinting transactions created by the Bitcoin Core wallet, change output
-amounts are now randomized. (#24494)
diff --git a/doc/release-notes-empty-template.md b/doc/release-notes-empty-template.md
deleted file mode 100644
index 8462714898..0000000000
--- a/doc/release-notes-empty-template.md
+++ /dev/null
@@ -1,99 +0,0 @@
-*The release notes draft is a temporary file that can be added to by anyone. See
-[/doc/developer-notes.md#release-notes](/doc/developer-notes.md#release-notes)
-for the process.*
-
-*version* Release Notes Draft
-===============================
-
-Bitcoin Core version *version* is now available from:
-
- <https://bitcoincore.org/bin/bitcoin-core-*version*/>
-
-This release includes new features, various bug fixes and performance
-improvements, as well as updated translations.
-
-Please report bugs using the issue tracker at GitHub:
-
- <https://github.com/bitcoin/bitcoin/issues>
-
-To receive security and update notifications, please subscribe to:
-
- <https://bitcoincore.org/en/list/announcements/join/>
-
-How to Upgrade
-==============
-
-If you are running an older version, shut it down. Wait until it has completely
-shut down (which might take a few minutes in some cases), then run the
-installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on Mac)
-or `bitcoind`/`bitcoin-qt` (on Linux).
-
-Upgrading directly from a version of Bitcoin Core that has reached its EOL is
-possible, but it might take some time if the data directory needs to be migrated. Old
-wallet versions of Bitcoin Core are generally supported.
-
-Compatibility
-==============
-
-Bitcoin Core is supported and extensively tested on operating systems
-using the Linux kernel, macOS 10.15+, and Windows 7 and newer. Bitcoin
-Core should also work on most other Unix-like systems but is not as
-frequently tested on them. It is not recommended to use Bitcoin Core on
-unsupported systems.
-
-Notable changes
-===============
-
-P2P and network changes
------------------------
-
-Updated RPCs
-------------
-
-
-Changes to wallet related RPCs can be found in the Wallet section below.
-
-New RPCs
---------
-
-Build System
-------------
-
-Updated settings
-----------------
-
-
-Changes to GUI or wallet related settings can be found in the GUI or Wallet section below.
-
-New settings
-------------
-
-Tools and Utilities
--------------------
-
-Wallet
-------
-
-GUI changes
------------
-
-Low-level changes
-=================
-
-RPC
----
-
-Tests
------
-
-*version* change log
-====================
-
-Credits
-=======
-
-Thanks to everyone who directly contributed to this release:
-
-
-As well as to everyone that helped with translations on
-[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 35f0713879..24920ba450 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -1,13 +1,12 @@
-*The release notes draft is a temporary file that can be added to by anyone. See
-[/doc/developer-notes.md#release-notes](/doc/developer-notes.md#release-notes)
-for the process.*
+24.0.1 Release Notes
+====================
-*version* Release Notes Draft
-===============================
+Due to last-minute issues (#26616), 24.0, although tagged, was never fully
+announced or released.
-Bitcoin Core version *version* is now available from:
+Bitcoin Core version 24.0.1 is now available from:
- <https://bitcoincore.org/bin/bitcoin-core-*version*/>
+ <https://bitcoincore.org/bin/bitcoin-core-24.0.1/>
This release includes new features, various bug fixes and performance
improvements, as well as updated translations.
@@ -25,7 +24,7 @@ How to Upgrade
If you are running an older version, shut it down. Wait until it has completely
shut down (which might take a few minutes in some cases), then run the
-installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on Mac)
+installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on macOS)
or `bitcoind`/`bitcoin-qt` (on Linux).
Upgrading directly from a version of Bitcoin Core that has reached its EOL is
@@ -41,12 +40,86 @@ Core should also work on most other Unix-like systems but is not as
frequently tested on them. It is not recommended to use Bitcoin Core on
unsupported systems.
+Notice of new option for transaction replacement policies
+=========================================================
+
+This version of Bitcoin Core adds a new `mempoolfullrbf` configuration
+option which allows users to change the policy their individual node
+will use for relaying and mining unconfirmed transactions. The option
+defaults to the same policy that was used in previous releases and no
+changes to node policy will occur if everyone uses the default.
+
+Some Bitcoin services today expect that the first version of an
+unconfirmed transaction that they see will be the version of the
+transaction that ultimately gets confirmed---a transaction acceptance
+policy sometimes called "first-seen".
+
+The Bitcoin Protocol does not, and cannot, provide any assurance that
+the first version of an unconfirmed transaction seen by a particular
+node will be the version that gets confirmed. If there are multiple
+versions of the same unconfirmed transaction available, only the miner
+who includes one of those transactions in a block gets to decide which
+version of the transaction gets confirmed.
+
+Despite this lack of assurance, multiple merchants and services today
+still make this assumption.
+
+There are several benefits to users from removing this *first-seen*
+simplification. One key benefit, the ability for the sender of a
+transaction to replace it with an alternative version paying higher
+fees, was realized in [Bitcoin Core 0.12.0][] (February 2016) with the
+introduction of [BIP125][] opt-in Replace By Fee (RBF).
+
+Since then, there has been discussion about completely removing the
+first-seen simplification and allowing users to replace any of their
+older unconfirmed transactions with newer transactions, a feature called
+*full-RBF*. This release includes a `mempoolfullrbf` configuration
+option that allows enabling full-RBF, although it defaults to off
+(allowing only opt-in RBF).
+
+Several alternative node implementations have already enabled full-RBF by
+default for years, and several contributors to Bitcoin Core are
+advocating for enabling full-RBF by default in a future version of
+Bitcoin Core.
+
+As more nodes that participate in relay and mining begin enabling
+full-RBF, replacement of unconfirmed transactions by ones offering higher
+fees may rapidly become more reliable.
+
+Contributors to this project strongly recommend that merchants and services
+not accept unconfirmed transactions as final, and if they insist on doing so,
+to take the appropriate steps to ensure they have some recourse or plan for
+when their assumptions do not hold.
+
+[Bitcoin Core 0.12.0]: https://bitcoincore.org/en/releases/0.12.0/#opt-in-replace-by-fee-transactions
+[bip125]: https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki
+
Notable changes
===============
P2P and network changes
-----------------------
+- To address a potential denial-of-service, the logic to download headers from peers
+ has been reworked. This is particularly relevant for nodes starting up for the
+ first time (or for nodes which are starting up after being offline for a long time).
+
+ Whenever headers are received from a peer that have a total chainwork that is either
+ less than the node's `-minimumchainwork` value or is sufficiently below the work at
+ the node's tip, a "presync" phase will begin, in which the node will download the
+ peer's headers and verify the cumulative work on the peer's chain, prior to storing
+ those headers permanently. Once that cumulative work is verified to be sufficiently high,
+ the headers will be redownloaded from that peer and fully validated and stored.
+
+ This may result in initial headers sync taking longer for new nodes starting up for
+ the first time, both because the headers will be downloaded twice, and because the effect
+ of a peer disconnecting during the presync phase (or while the node's best headers chain has less
+ than `-minimumchainwork`), will result in the node needing to use the headers presync mechanism
+ with the next peer as well (downloading the headers twice, again). (#25717)
+
+- With I2P connections, a new, transient address is used for each outbound
+ connection if `-i2pacceptincoming=0`. (#25355)
+
Updated RPCs
------------
@@ -69,52 +142,250 @@ Updated RPCs
The same fee fields can be accessed through the `fees` object in the result.
The top-level fee fields were previously deprecated in 23.0. (#25204)
+- The `getpeerinfo` RPC has been updated with a new `presynced_headers` field,
+ indicating the progress on the presync phase mentioned in the
+ "P2P and network changes" section above.
+
Changes to wallet related RPCs can be found in the Wallet section below.
New RPCs
--------
-Build System
-------------
+- The `sendall` RPC spends specific UTXOs to one or more recipients
+ without creating change. By default, the `sendall` RPC will spend
+ every UTXO in the wallet. `sendall` is useful to empty wallets or to
+ create a changeless payment from select UTXOs. When creating a payment
+ from a specific amount for which the recipient incurs the transaction
+ fee, continue to use the `subtractfeefromamount` option via the
+ `send`, `sendtoaddress`, or `sendmany` RPCs. (#24118)
+
+- A new `gettxspendingprevout` RPC has been added, which scans the mempool to find
+ transactions spending any of the given outpoints. (#24408)
+
+- The `simulaterawtransaction` RPC iterates over the inputs and outputs of the given
+ transactions, and tallies up the balance change for the given wallet. This can be
+ useful e.g. when verifying that a coin join like transaction doesn't contain unexpected
+ inputs that the wallet will then sign for unintentionally. (#22751)
+
+Updated REST APIs
+-----------------
-Updated settings
-----------------
+- The `/headers/` and `/blockfilterheaders/` endpoints have been updated to use
+ a query parameter instead of path parameter to specify the result count. The
+ count parameter is now optional, and defaults to 5 for both endpoints. The old
+ endpoints are still functional, and have no documented behaviour change.
+ For `/headers`, use
+ `GET /rest/headers/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>`
+ instead of
+ `GET /rest/headers/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated)
-Changes to GUI or wallet related settings can be found in the GUI or Wallet section below.
+ For `/blockfilterheaders/`, use
+ `GET /rest/blockfilterheaders/<FILTERTYPE>/<BLOCK-HASH>.<bin|hex|json>?count=<COUNT=5>`
+ instead of
+ `GET /rest/blockfilterheaders/<FILTERTYPE>/<COUNT>/<BLOCK-HASH>.<bin|hex|json>` (deprecated)
+
+ (#24098)
+
+Build System
+------------
+
+- Guix builds are now reproducible across architectures (x86_64 & aarch64). (#21194)
New settings
------------
-Tools and Utilities
--------------------
+- A new `mempoolfullrbf` option has been added, which enables the mempool to
+ accept transaction replacement without enforcing BIP125 replaceability
+ signaling. (#25353)
Wallet
------
+- The `-walletrbf` startup option will now default to `true`. The
+ wallet will now default to opt-in RBF on transactions that it creates. (#25610)
+
+- The `replaceable` option for the `createrawtransaction` and
+ `createpsbt` RPCs will now default to `true`. Transactions created
+ with these RPCs will default to having opt-in RBF enabled. (#25610)
+
+- The `wsh()` output descriptor was extended with Miniscript support. You can import Miniscript
+ descriptors for P2WSH in a watchonly wallet to track coins, but you can't spend from them using
+ the Bitcoin Core wallet yet.
+ You can find more about Miniscript on the [reference website](https://bitcoin.sipa.be/miniscript/). (#24148)
+
+- The `tr()` output descriptor now supports multisig scripts through the `multi_a()` and
+ `sortedmulti_a()` functions. (#24043)
+
+- To help prevent fingerprinting transactions created by the Bitcoin Core wallet, change output
+ amounts are now randomized. (#24494)
+
+- The `listtransactions`, `gettransaction`, and `listsinceblock`
+ RPC methods now include a wtxid field (hash of serialized transaction,
+ including witness data) for each transaction. (#24198)
+
+- The `listsinceblock`, `listtransactions` and `gettransaction` output now contain a new
+ `parent_descs` field for every "receive" entry. (#25504)
+
+- A new optional `include_change` parameter was added to the `listsinceblock` command.
+
- RPC `getreceivedbylabel` now returns an error, "Label not found
in wallet" (-4), if the label is not in the address book. (#25122)
+Migrating Legacy Wallets to Descriptor Wallets
+---------------------------------------------
+
+An experimental RPC `migratewallet` has been added to migrate Legacy (non-descriptor) wallets to
+Descriptor wallets. More information about the migration process is available in the
+[documentation](https://github.com/bitcoin/bitcoin/blob/master/doc/managing-wallets.md#migrating-legacy-wallets-to-descriptor-wallets).
+
GUI changes
-----------
+- A new menu item to restore a wallet from a backup file has been added (gui#471).
+
+- Configuration changes made in the bitcoin GUI (such as the pruning setting,
+proxy settings, UPNP preferences) are now saved to `<datadir>/settings.json`
+file rather than to the Qt settings backend (windows registry or unix desktop
+config files), so these settings will now apply to bitcoind, instead of being
+ignored. (#15936, gui#602)
+
+- Also, the interaction between GUI settings and `bitcoin.conf` settings is
+simplified. Settings from `bitcoin.conf` are now displayed normally in the GUI
+settings dialog, instead of in a separate warning message ("Options set in this
+dialog are overridden by the configuration file: -setting=value"). And these
+settings can now be edited because `settings.json` values take precedence over
+`bitcoin.conf` values. (#15936)
+
Low-level changes
=================
RPC
---
-Tests
------
+- The `deriveaddresses`, `getdescriptorinfo`, `importdescriptors` and `scantxoutset` commands now
+ accept Miniscript expression within a `wsh()` descriptor. (#24148)
-*version* change log
-====================
+- The `getaddressinfo`, `decodescript`, `listdescriptors` and `listunspent` commands may now output
+ a Miniscript descriptor inside a `wsh()` where a `wsh(raw())` descriptor was previously returned. (#24148)
Credits
=======
Thanks to everyone who directly contributed to this release:
+- /dev/fd0
+- 0xb10c
+- Adam Jonas
+- akankshakashyap
+- Ali Sherief
+- amadeuszpawlik
+- Andreas Kouloumos
+- Andrew Chow
+- Anthony Towns
+- Antoine Poinsot
+- Antoine Riard
+- Aurèle Oulès
+- avirgovi
+- Ayush Sharma
+- Baas
+- Ben Woosley
+- BrokenProgrammer
+- brunoerg
+- brydinh
+- Bushstar
+- Calvin Kim
+- CAnon
+- Carl Dong
+- chinggg
+- Cory Fields
+- Daniel Kraft
+- Daniela Brozzoni
+- darosior
+- Dave Scotese
+- David Bakin
+- dergoegge
+- dhruv
+- Dimitri
+- dontbyte
+- Duncan Dean
+- eugene
+- Eunoia
+- Fabian Jahr
+- furszy
+- Gleb Naumenko
+- glozow
+- Greg Weber
+- Gregory Sanders
+- gruve-p
+- Hennadii Stepanov
+- hiago
+- Igor Bubelov
+- ishaanam
+- Jacob P.
+- Jadi
+- James O'Beirne
+- Janna
+- Jarol Rodriguez
+- Jeremy Rand
+- Jeremy Rubin
+- jessebarton
+- João Barbosa
+- John Newbery
+- Jon Atack
+- Josiah Baker
+- Karl-Johan Alm
+- KevinMusgrave
+- Kiminuo
+- klementtan
+- Kolby Moroz
+- kouloumos
+- Kristaps Kaupe
+- Larry Ruane
+- Luke Dashjr
+- MarcoFalke
+- Marnix
+- Martin Leitner-Ankerl
+- Martin Zumsande
+- Michael Dietz
+- Michael Folkson
+- Michael Ford
+- Murch
+- mutatrum
+- muxator
+- Oskar Mendel
+- Pablo Greco
+- pasta
+- Patrick Strateman
+- Pavol Rusnak
+- Peter Bushnell
+- phyBrackets
+- Pieter Wuille
+- practicalswift
+- randymcmillan
+- Robert Spigler
+- Russell Yanofsky
+- S3RK
+- Samer Afach
+- Sebastian Falbesoner
+- Seibart Nedor
+- Shashwat
+- Sjors Provoost
+- Smlep
+- sogoagain
+- Stacie
+- Stéphan Vuylsteke
+- Suhail Saqan
+- Suhas Daftuar
+- t-bast
+- TakeshiMusgrave
+- Vasil Dimov
+- W. J. van der Laan
+- w0xlt
+- whiteh0rse
+- willcl-ark
+- William Casarin
+- Yancy Ribbens
As well as to everyone that helped with translations on
[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
diff --git a/doc/release-notes/release-notes-24408.md b/doc/release-notes/release-notes-24408.md
deleted file mode 100644
index 1072ec786a..0000000000
--- a/doc/release-notes/release-notes-24408.md
+++ /dev/null
@@ -1,5 +0,0 @@
-New RPCs
---------
-
-- A new `gettxspendingprevout` RPC has been added, which scans the mempool to find
- transactions spending any of the given outpoints. (#24408) \ No newline at end of file
diff --git a/share/examples/bitcoin.conf b/share/examples/bitcoin.conf
index 5bee4bf92e..bbbbe66404 100644
--- a/share/examples/bitcoin.conf
+++ b/share/examples/bitcoin.conf
@@ -1 +1,685 @@
-# This is a placeholder file. Please follow the instructions in `contrib/devtools/README.md` to generate a bitcoin.conf file.
+##
+## bitcoin.conf configuration file.
+## Generated by contrib/devtools/gen-bitcoin-conf.sh.
+##
+## Lines beginning with # are comments.
+## All possible configuration options are provided. To use, copy this file
+## to your data directory (default or specified by -datadir), uncomment
+## options you would like to change, and save the file.
+##
+
+
+### Options
+
+
+# Execute command when an alert is raised (%s in cmd is replaced by
+# message)
+#alertnotify=<cmd>
+
+# If this block is in the chain assume that it and its ancestors are valid
+# and potentially skip their script verification (0 to verify all,
+# default:
+# 00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd,
+# testnet:
+# 0000000000000004877fa2d36316398528de4f347df2f8a96f76613a298ce060,
+# signet:
+# 000000d1a0e224fa4679d2fb2187ba55431c284fa1b74cbc8cfda866fd4d2c09)
+#assumevalid=<hex>
+
+# Maintain an index of compact filters by block (default: 0, values:
+# basic). If <type> is not supplied or if <type> = 1, indexes for
+# all known types are enabled.
+#blockfilterindex=<type>
+
+# Execute command when the best block changes (%s in cmd is replaced by
+# block hash)
+#blocknotify=<cmd>
+
+# Extra transactions to keep in memory for compact block reconstructions
+# (default: 100)
+#blockreconstructionextratxn=<n>
+
+# Specify directory to hold blocks subdirectory for *.dat files (default:
+# <datadir>)
+#blocksdir=<dir>
+
+# Whether to reject transactions from network peers. Automatic broadcast
+# and rebroadcast of any transactions from inbound peers is
+# disabled, unless the peer has the 'forcerelay' permission. RPC
+# transactions are not affected. (default: 0)
+#blocksonly=1
+
+# Maintain coinstats index used by the gettxoutsetinfo RPC (default: 0)
+#coinstatsindex=1
+
+# Specify path to read-only configuration file. Relative paths will be
+# prefixed by datadir location (only useable from command line, not
+# configuration file) (default: bitcoin.conf)
+#conf=<file>
+
+# Run in the background as a daemon and accept commands (default: 0)
+#daemon=1
+
+# Wait for initialization to be finished before exiting. This implies
+# -daemon (default: 0)
+#daemonwait=1
+
+# Specify data directory
+#datadir=<dir>
+
+# Maximum database cache size <n> MiB (4 to 16384, default: 450). In
+# addition, unused mempool memory is shared for this cache (see
+# -maxmempool).
+#dbcache=<n>
+
+# Specify location of debug log file. Relative paths will be prefixed by a
+# net-specific datadir location. (-nodebuglogfile to disable;
+# default: debug.log)
+#debuglogfile=<file>
+
+# Specify additional configuration file, relative to the -datadir path
+# (only useable from configuration file, not command line)
+#includeconf=<file>
+
+# Imports blocks from external file on startup
+#loadblock=<file>
+
+# Keep the transaction memory pool below <n> megabytes (default: 300)
+#maxmempool=<n>
+
+# Keep at most <n> unconnectable transactions in memory (default: 100)
+#maxorphantx=<n>
+
+# Do not keep transactions in the mempool longer than <n> hours (default:
+# 336)
+#mempoolexpiry=<n>
+
+# Set the number of script verification threads (-10 to 15, 0 = auto, <0 =
+# leave that many cores free, default: 0)
+#par=<n>
+
+# Whether to save the mempool on shutdown and load on restart (default: 1)
+#persistmempool=1
+
+# Specify pid file. Relative paths will be prefixed by a net-specific
+# datadir location. (default: bitcoind.pid)
+#pid=<file>
+
+# 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, >=550 =
+# automatically prune block files to stay under the specified
+# target size in MiB)
+#prune=<n>
+
+# Rebuild chain state and block index from the blk*.dat files on disk.
+# This will also rebuild active optional indexes.
+#reindex=1
+
+# Rebuild chain state from the currently indexed blocks. When in pruning
+# mode or if blocks on disk might be corrupted, use full -reindex
+# instead. Deactivate all optional indexes before running this.
+#reindex-chainstate=1
+
+# Use the experimental syscall sandbox in the specified mode
+# (-sandbox=log-and-abort or -sandbox=abort). Allow only expected
+# syscalls to be used by bitcoind. Note that this is an
+# experimental new feature that may cause bitcoind to exit or crash
+# unexpectedly: use with caution. In the "log-and-abort" mode the
+# invocation of an unexpected syscall results in a debug handler
+# being invoked which will log the incident and terminate the
+# program (without executing the unexpected syscall). In the
+# "abort" mode the invocation of an unexpected syscall results in
+# the entire process being killed immediately by the kernel without
+# executing the unexpected syscall.
+#sandbox=<mode>
+
+# 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 bitcoin.conf instead for custom settings).
+# Relative paths will be prefixed by datadir location. (default:
+# settings.json)
+#settings=<file>
+
+# Execute command on startup.
+#startupnotify=<cmd>
+
+# Create new files with system default permissions, instead of umask 077
+# (only effective with disabled wallet functionality)
+#sysperms=1
+
+# Maintain a full transaction index, used by the getrawtransaction rpc
+# call (default: 0)
+#txindex=1
+
+# Print version and exit
+#version=1
+
+
+### Connection options
+
+
+# Add a node to connect to and attempt to keep the connection open (see
+# the addnode RPC help for more info). This option can be specified
+# multiple times to add multiple nodes; connections are limited to
+# 8 at a time and are counted separately from the -maxconnections
+# limit.
+#addnode=<ip>
+
+# Specify asn mapping used for bucketing of the peers (default:
+# ip_asn.map). Relative paths will be prefixed by the net-specific
+# datadir location.
+#asmap=<file>
+
+# Default duration (in seconds) of manually configured bans (default:
+# 86400)
+#bantime=<n>
+
+# Bind to given address and always listen on it (default: 0.0.0.0). Use
+# [host]:port notation for IPv6. Append =onion to tag any incoming
+# connections to that address and port as incoming Tor connections
+# (default: 127.0.0.1:8334=onion, testnet: 127.0.0.1:18334=onion,
+# signet: 127.0.0.1:38334=onion, regtest: 127.0.0.1:18445=onion)
+#bind=<addr>[:<port>][=onion]
+
+# If set, then this host is configured for CJDNS (connecting to fc00::/8
+# addresses would lead us to the CJDNS network, see doc/cjdns.md)
+# (default: 0)
+#cjdnsreachable=1
+
+# Connect only to the specified node; -noconnect disables automatic
+# connections (the rules for this peer are the same as for
+# -addnode). This option can be specified multiple times to connect
+# to multiple nodes.
+#connect=<ip>
+
+# Discover own IP addresses (default: 1 when listening and no -externalip
+# or -proxy)
+#discover=1
+
+# Allow DNS lookups for -addnode, -seednode and -connect (default: 1)
+#dns=1
+
+# Query for peer addresses via DNS lookup, if low on addresses (default: 1
+# unless -connect used)
+#dnsseed=1
+
+# Specify your own public address
+#externalip=<ip>
+
+# Allow fixed seeds if DNS seeds don't provide peers (default: 1)
+#fixedseeds=1
+
+# Always query for peer addresses via DNS lookup (default: 0)
+#forcednsseed=1
+
+# If set and -i2psam is also set then incoming I2P connections are
+# accepted via the SAM proxy. If this is not set but -i2psam is set
+# then only outgoing connections will be made to the I2P network.
+# Ignored if -i2psam is not set. Listening for incoming I2P
+# connections is done through the SAM proxy, not by binding to a
+# local address and port (default: 1)
+#i2pacceptincoming=1
+
+# I2P SAM proxy to reach I2P peers and accept I2P connections (default:
+# none)
+#i2psam=<ip:port>
+
+# Accept connections from outside (default: 1 if no -proxy or -connect)
+#listen=1
+
+# Automatically create Tor onion service (default: 1)
+#listenonion=1
+
+# Maintain at most <n> connections to peers (default: 125). This limit
+# does not apply to connections manually added via -addnode or the
+# addnode RPC, which have a separate limit of 8.
+#maxconnections=<n>
+
+# Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)
+#maxreceivebuffer=<n>
+
+# Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)
+#maxsendbuffer=<n>
+
+# Maximum allowed median peer time offset adjustment. Local perspective of
+# time may be influenced by outbound peers forward or backward by
+# this amount (default: 4200 seconds).
+#maxtimeadjustment=1
+
+# Tries to keep outbound traffic under the given target per 24h. Limit
+# does not apply to peers with 'download' permission or blocks
+# created within past week. 0 = no limit (default: 0M). Optional
+# suffix units [k|K|m|M|g|G|t|T] (default: M). Lowercase is 1000
+# base while uppercase is 1024 base
+#maxuploadtarget=<n>
+
+# Use NAT-PMP to map the listening port (default: 0)
+#natpmp=1
+
+# Enable all P2P network activity (default: 1). Can be changed by the
+# setnetworkactive RPC command
+#networkactive=1
+
+# Use separate SOCKS5 proxy to reach peers via Tor onion services, set
+# -noonion to disable (default: -proxy)
+#onion=<ip:port>
+
+# Make automatic outbound connections only to network <net> (ipv4, ipv6,
+# onion, i2p, cjdns). Inbound and manual connections are not
+# affected by this option. It can be specified multiple times to
+# allow multiple networks.
+#onlynet=<net>
+
+# Serve compact block filters to peers per BIP 157 (default: 0)
+#peerblockfilters=1
+
+# Support filtering of blocks and transaction with bloom filters (default:
+# 0)
+#peerbloomfilters=1
+
+# Listen for connections on <port>. Nodes not using the default ports
+# (default: 8333, testnet: 18333, signet: 38333, regtest: 18444)
+# are unlikely to get incoming connections. Not relevant for I2P
+# (see doc/i2p.md).
+#port=<port>
+
+# Connect through SOCKS5 proxy, set -noproxy to disable (default:
+# disabled)
+#proxy=<ip:port>
+
+# Randomize credentials for every proxy connection. This enables Tor
+# stream isolation (default: 1)
+#proxyrandomize=1
+
+# Connect to a node to retrieve peer addresses, and disconnect. This
+# option can be specified multiple times to connect to multiple
+# nodes.
+#seednode=<ip>
+
+# Specify socket connection timeout in milliseconds. If an initial attempt
+# to connect is unsuccessful after this amount of time, drop it
+# (minimum: 1, default: 5000)
+#timeout=<n>
+
+# Tor control port to use if onion listening enabled (default:
+# 127.0.0.1:9051)
+#torcontrol=<ip>:<port>
+
+# Tor control port password (default: empty)
+#torpassword=<pass>
+
+# Use UPnP to map the listening port (default: 0)
+#upnp=1
+
+# Bind to the given address and add permission flags to the peers
+# connecting to it. Use [host]:port notation for IPv6. Allowed
+# permissions: bloomfilter (allow requesting BIP37 filtered blocks
+# and transactions), noban (do not ban for misbehavior; implies
+# download), forcerelay (relay transactions that are already in the
+# mempool; implies relay), relay (relay even in -blocksonly mode,
+# and unlimited transaction announcements), mempool (allow
+# requesting BIP35 mempool contents), download (allow getheaders
+# during IBD, no disconnect after maxuploadtarget limit), addr
+# (responses to GETADDR avoid hitting the cache and contain random
+# records with the most up-to-date info). Specify multiple
+# permissions separated by commas (default:
+# download,noban,mempool,relay). Can be specified multiple times.
+#whitebind=<[permissions@]addr>
+
+# Add permission flags to the peers connecting from the given IP address
+# (e.g. 1.2.3.4) or CIDR-notated network (e.g. 1.2.3.0/24). Uses
+# the same permissions as -whitebind. Can be specified multiple
+# times.
+#whitelist=<[permissions@]IP address or network>
+
+
+### Wallet options
+
+
+# What type of addresses to use ("legacy", "p2sh-segwit", "bech32", or
+# "bech32m", default: "bech32")
+#addresstype=1
+
+# Group outputs by address, selecting many (possibly all) or none, instead
+# of selecting on a per-output basis. Privacy is improved as
+# addresses are mostly swept with fewer transactions and outputs
+# are aggregated in clean change addresses. It may result in higher
+# fees due to less optimal coin selection caused by this added
+# limitation and possibly a larger-than-necessary number of inputs
+# being used. Always enabled for wallets with "avoid_reuse"
+# enabled, otherwise default: 0.
+#avoidpartialspends=1
+
+# What type of change to use ("legacy", "p2sh-segwit", "bech32", or
+# "bech32m"). Default is "legacy" when -addresstype=legacy, else it
+# is an implementation detail.
+#changetype=1
+
+# The maximum feerate (in BTC/kvB) at which transaction building may use
+# more inputs than strictly necessary so that the wallet's UTXO
+# pool can be reduced (default: 0.0001).
+#consolidatefeerate=<amt>
+
+# Do not load the wallet and disable wallet RPC calls
+#disablewallet=1
+
+# The fee rate (in BTC/kvB) that indicates your tolerance for discarding
+# change by adding it to the fee (default: 0.0001). Note: An output
+# is discarded if it is dust at this rate, but we will always
+# discard up to the dust relay fee and a discard fee above that is
+# limited by the fee estimate for the longest target
+#discardfee=<amt>
+
+# A fee rate (in BTC/kvB) that will be used when fee estimation has
+# insufficient data. 0 to entirely disable the fallbackfee feature.
+# (default: 0.00)
+#fallbackfee=<amt>
+
+# Set key pool size to <n> (default: 1000). Warning: Smaller sizes may
+# increase the risk of losing funds when restoring from an old
+# backup, if none of the addresses in the original keypool have
+# been used.
+#keypool=<n>
+
+# Spend up to this amount in additional (absolute) fees (in BTC) if it
+# allows the use of partial spend avoidance (default: 0.00)
+#maxapsfee=<n>
+
+# Fee rates (in BTC/kvB) smaller than this are considered zero fee for
+# transaction creation (default: 0.00001)
+#mintxfee=<amt>
+
+# Fee rate (in BTC/kvB) to add to transactions you send (default: 0.00)
+#paytxfee=<amt>
+
+# External signing tool, see doc/external-signer.md
+#signer=<cmd>
+
+# Spend unconfirmed change when sending transactions (default: 1)
+#spendzeroconfchange=1
+
+# If paytxfee is not set, include enough fee so transactions begin
+# confirmation on average within n blocks (default: 6)
+#txconfirmtarget=<n>
+
+# Specify wallet path to load at startup. Can be used multiple times to
+# load multiple wallets. Path is to a directory containing wallet
+# data and log files. If the path is not absolute, it is
+# interpreted relative to <walletdir>. This only loads existing
+# wallets and does not create new ones. For backwards compatibility
+# this also accepts names of existing top-level data files in
+# <walletdir>.
+#wallet=<path>
+
+# Make the wallet broadcast transactions (default: 1)
+#walletbroadcast=1
+
+# Specify directory to hold wallets (default: <datadir>/wallets if it
+# exists, otherwise <datadir>)
+#walletdir=<dir>
+
+# Execute command when a wallet transaction changes. %s in cmd is replaced
+# by TxID, %w is replaced by wallet name, %b is replaced by the
+# hash of the block including the transaction (set to 'unconfirmed'
+# if the transaction is not included) and %h is replaced by the
+# block height (-1 if not included). %w is not currently
+# implemented on windows. On systems where %w is supported, it
+# should NOT be quoted because this would break shell escaping used
+# to invoke the command.
+#walletnotify=<cmd>
+
+# Send transactions with full-RBF opt-in enabled (RPC only, default: 1)
+#walletrbf=1
+
+
+### ZeroMQ notification options
+
+
+# Enable publish hash block in <address>
+#zmqpubhashblock=<address>
+
+# Set publish hash block outbound message high water mark (default: 1000)
+#zmqpubhashblockhwm=<n>
+
+# Enable publish hash transaction in <address>
+#zmqpubhashtx=<address>
+
+# Set publish hash transaction outbound message high water mark (default:
+# 1000)
+#zmqpubhashtxhwm=<n>
+
+# Enable publish raw block in <address>
+#zmqpubrawblock=<address>
+
+# Set publish raw block outbound message high water mark (default: 1000)
+#zmqpubrawblockhwm=<n>
+
+# Enable publish raw transaction in <address>
+#zmqpubrawtx=<address>
+
+# Set publish raw transaction outbound message high water mark (default:
+# 1000)
+#zmqpubrawtxhwm=<n>
+
+# Enable publish hash block and tx sequence in <address>
+#zmqpubsequence=<address>
+
+# Set publish hash sequence message high water mark (default: 1000)
+#zmqpubsequencehwm=<n>
+
+
+### Debugging/Testing options
+
+
+# Output debug and trace logging (default: -nodebug, supplying <category>
+# is optional). If <category> is not supplied or if <category> = 1,
+# output all debug and trace logging. <category> can be: addrman,
+# bench, blockstorage, cmpctblock, coindb, estimatefee, http, i2p,
+# ipc, leveldb, libevent, mempool, mempoolrej, net, proxy, prune,
+# qt, rand, reindex, rpc, selectcoins, tor, util, validation,
+# walletdb, zmq. This option can be specified multiple times to
+# output multiple categories.
+#debug=<category>
+
+# Exclude debug and trace logging for a category. Can be used in
+# conjunction with -debug=1 to output debug and trace logging for
+# all categories except the specified category. This option can be
+# specified multiple times to exclude multiple categories.
+#debugexclude=<category>
+
+# Print help message with debugging options and exit
+#help-debug=1
+
+# Include IP addresses in debug output (default: 0)
+#logips=1
+
+# Prepend debug output with name of the originating source location
+# (source file, line number and function name) (default: 0)
+#logsourcelocations=1
+
+# Prepend debug output with name of the originating thread (only available
+# on platforms supporting thread_local) (default: 0)
+#logthreadnames=1
+
+# Prepend debug output with timestamp (default: 1)
+#logtimestamps=1
+
+# Maximum total fees (in BTC) to use in a single wallet transaction;
+# setting this too low may abort large transactions (default: 0.10)
+#maxtxfee=<amt>
+
+# Send trace/debug info to console (default: 1 when no -daemon. To disable
+# logging to file, set -nodebuglogfile)
+#printtoconsole=1
+
+# Shrink debug.log file on client startup (default: 1 when no -debug)
+#shrinkdebugfile=1
+
+# Append comment to the user agent string
+#uacomment=<cmt>
+
+
+### Chain selection options
+
+
+# Use the chain <chain> (default: main). Allowed values: main, test,
+# signet, regtest
+#chain=<chain>
+
+# Use the signet chain. Equivalent to -chain=signet. Note that the network
+# is defined by the -signetchallenge parameter
+#signet=1
+
+# Blocks must satisfy the given script to be considered valid (only for
+# signet networks; defaults to the global default signet test
+# network challenge)
+#signetchallenge=1
+
+# Specify a seed node for the signet network, in the hostname[:port]
+# format, e.g. sig.net:1234 (may be used multiple times to specify
+# multiple seed nodes; defaults to the global default signet test
+# network seed node(s))
+#signetseednode=1
+
+# Use the test chain. Equivalent to -chain=test.
+#testnet=1
+
+
+### Node relay options
+
+
+# Equivalent bytes per sigop in transactions for relay and mining
+# (default: 20)
+#bytespersigop=1
+
+# Relay and mine data carrier transactions (default: 1)
+#datacarrier=1
+
+# Maximum size of data in data carrier transactions we relay and mine
+# (default: 83)
+#datacarriersize=1
+
+# Accept transaction replace-by-fee without requiring replaceability
+# signaling (default: 0)
+#mempoolfullrbf=1
+
+# Fees (in BTC/kvB) smaller than this are considered zero fee for
+# relaying, mining and transaction creation (default: 0.00001)
+#minrelaytxfee=<amt>
+
+# Relay non-P2SH multisig (default: 1)
+#permitbaremultisig=1
+
+# Add 'forcerelay' permission to whitelisted inbound peers with default
+# permissions. This will relay transactions even if the
+# transactions were already in the mempool. (default: 0)
+#whitelistforcerelay=1
+
+# Add 'relay' permission to whitelisted inbound peers with default
+# permissions. This will accept relayed transactions even when not
+# relaying transactions (default: 1)
+#whitelistrelay=1
+
+
+### Block creation options
+
+
+# Set maximum BIP141 block weight (default: 3996000)
+#blockmaxweight=<n>
+
+# Set lowest fee rate (in BTC/kvB) for transactions to be included in
+# block creation. (default: 0.00001)
+#blockmintxfee=<amt>
+
+
+### RPC server options
+
+
+# Accept public REST requests (default: 0)
+#rest=1
+
+# Allow JSON-RPC connections from specified source. Valid for <ip> are a
+# single IP (e.g. 1.2.3.4), a network/netmask (e.g.
+# 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This
+# option can be specified multiple times
+#rpcallowip=<ip>
+
+# Username and HMAC-SHA-256 hashed password for JSON-RPC connections. The
+# field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A
+# canonical python script is included in share/rpcauth. The client
+# then connects normally using the
+# rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This
+# option can be specified multiple times
+#rpcauth=<userpw>
+
+# Bind to given address to listen for JSON-RPC connections. Do not expose
+# the RPC server to untrusted networks such as the public internet!
+# This option is ignored unless -rpcallowip is also passed. Port is
+# optional and overrides -rpcport. Use [host]:port notation for
+# IPv6. This option can be specified multiple times (default:
+# 127.0.0.1 and ::1 i.e., localhost)
+#rpcbind=<addr>[:port]
+
+# Location of the auth cookie. Relative paths will be prefixed by a
+# net-specific datadir location. (default: data dir)
+#rpccookiefile=<loc>
+
+# Password for JSON-RPC connections
+#rpcpassword=<pw>
+
+# Listen for JSON-RPC connections on <port> (default: 8332, testnet:
+# 18332, signet: 38332, regtest: 18443)
+#rpcport=<port>
+
+# Sets the serialization of raw transaction or block hex returned in
+# non-verbose mode, non-segwit(0) or segwit(1) (default: 1)
+#rpcserialversion=1
+
+# Set the number of threads to service RPC calls (default: 4)
+#rpcthreads=<n>
+
+# Username for JSON-RPC connections
+#rpcuser=<user>
+
+# Set a whitelist to filter incoming RPC calls for a specific user. The
+# field <whitelist> comes in the format: <USERNAME>:<rpc 1>,<rpc
+# 2>,...,<rpc n>. If multiple whitelists are set for a given user,
+# they are set-intersected. See -rpcwhitelistdefault documentation
+# for information on default whitelist behavior.
+#rpcwhitelist=<whitelist>
+
+# Sets default behavior for rpc whitelisting. Unless rpcwhitelistdefault
+# is set to 0, if any -rpcwhitelist is set, the rpc server acts as
+# if all rpc users are subject to empty-unless-otherwise-specified
+# whitelists. If rpcwhitelistdefault is set to 1 and no
+# -rpcwhitelist is set, rpc server acts as if all rpc users are
+# subject to empty whitelists.
+#rpcwhitelistdefault=1
+
+# Accept command line and JSON-RPC commands
+#server=1
+
+
+# [Sections]
+# Most options will apply to all networks. To confine an option to a specific
+# network, add it under the relevant section below.
+#
+# Note: If not specified under a network section, the options addnode, connect,
+# port, bind, rpcport, rpcbind, and wallet will only apply to mainnet.
+
+# Options for mainnet
+[main]
+
+# Options for testnet
+[test]
+
+# Options for signet
+[signet]
+
+# Options for regtest
+[regtest]
diff --git a/share/setup.nsi.in b/share/setup.nsi.in
index b31ba7a5b4..2ce798bd2d 100644
--- a/share/setup.nsi.in
+++ b/share/setup.nsi.in
@@ -75,13 +75,15 @@ Section -Main SEC0000
File @abs_top_builddir@/release/@BITCOIN_GUI_NAME@@EXEEXT@
File /oname=COPYING.txt @abs_top_srcdir@/COPYING
File /oname=readme.txt @abs_top_srcdir@/doc/README_windows.txt
+ File @abs_top_srcdir@/share/examples/bitcoin.conf
+ SetOutPath $INSTDIR\share\rpcauth
+ File @abs_top_srcdir@/share/rpcauth/*.*
SetOutPath $INSTDIR\daemon
File @abs_top_builddir@/release/@BITCOIN_DAEMON_NAME@@EXEEXT@
File @abs_top_builddir@/release/@BITCOIN_CLI_NAME@@EXEEXT@
File @abs_top_builddir@/release/@BITCOIN_TX_NAME@@EXEEXT@
File @abs_top_builddir@/release/@BITCOIN_WALLET_TOOL_NAME@@EXEEXT@
- SetOutPath $INSTDIR\doc
- File /r /x Makefile* @abs_top_srcdir@/doc\*.*
+ File @abs_top_builddir@/release/@BITCOIN_TEST_NAME@@EXEEXT@
SetOutPath $INSTDIR
WriteRegStr HKCU "${REGKEY}\Components" Main 1
SectionEnd
@@ -128,8 +130,9 @@ Section /o -un.Main UNSEC0000
Delete /REBOOTOK $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@
Delete /REBOOTOK $INSTDIR\COPYING.txt
Delete /REBOOTOK $INSTDIR\readme.txt
+ Delete /REBOOTOK $INSTDIR\bitcoin.conf
+ RMDir /r /REBOOTOK $INSTDIR\share
RMDir /r /REBOOTOK $INSTDIR\daemon
- RMDir /r /REBOOTOK $INSTDIR\doc
DeleteRegValue HKCU "${REGKEY}\Components" Main
SectionEnd
diff --git a/src/.clang-tidy b/src/.clang-tidy
index e9807d4cb7..9d78ccc959 100644
--- a/src/.clang-tidy
+++ b/src/.clang-tidy
@@ -1,13 +1,28 @@
Checks: '
-*,
bugprone-argument-comment,
+bugprone-use-after-move,
+misc-unused-using-decls,
modernize-use-default-member-init,
modernize-use-nullptr,
+performance-for-range-copy,
+performance-move-const-arg,
+performance-unnecessary-copy-initialization,
readability-redundant-declaration,
+readability-redundant-string-init,
'
WarningsAsErrors: '
bugprone-argument-comment,
+bugprone-use-after-move,
+misc-unused-using-decls,
modernize-use-default-member-init,
modernize-use-nullptr,
+performance-for-range-copy,
+performance-move-const-arg,
+performance-unnecessary-copy-initialization,
readability-redundant-declaration,
+readability-redundant-string-init,
'
+CheckOptions:
+ - key: performance-move-const-arg.CheckTriviallyCopyableMove
+ value: false
diff --git a/src/Makefile.am b/src/Makefile.am
index fa716af619..6364e00d1e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,7 @@ noinst_PROGRAMS =
TESTS =
BENCHMARKS =
-BITCOIN_INCLUDES=-I$(builddir) -I$(srcdir)/$(MINISKETCH_INCLUDE_DIR_INT) -I$(srcdir)/secp256k1/include -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS)
+BITCOIN_INCLUDES=-I$(builddir) -I$(srcdir)/$(MINISKETCH_INCLUDE_DIR_INT) -I$(srcdir)/secp256k1/include -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) $(LEVELDB_CPPFLAGS)
LIBBITCOIN_NODE=libbitcoin_node.a
LIBBITCOIN_COMMON=libbitcoin_common.a
@@ -133,9 +133,9 @@ BITCOIN_CORE_H = \
clientversion.h \
coins.h \
common/bloom.h \
- compat.h \
compat/assumptions.h \
compat/byteswap.h \
+ compat/compat.h \
compat/cpuid.h \
compat/endian.h \
compressor.h \
@@ -151,6 +151,7 @@ BITCOIN_CORE_H = \
external_signer.h \
flatfile.h \
fs.h \
+ headerssync.h \
httprpc.h \
httpserver.h \
i2p.h \
@@ -169,10 +170,15 @@ BITCOIN_CORE_H = \
interfaces/ipc.h \
interfaces/node.h \
interfaces/wallet.h \
+ kernel/chain.h \
kernel/chainstatemanager_opts.h \
kernel/checks.h \
kernel/coinstats.h \
kernel/context.h \
+ kernel/mempool_limits.h \
+ kernel/mempool_options.h \
+ kernel/mempool_persist.h \
+ kernel/validation_cache_sizes.h \
key.h \
key_io.h \
logging.h \
@@ -192,17 +198,23 @@ BITCOIN_CORE_H = \
node/caches.h \
node/chainstate.h \
node/coin.h \
+ node/connection_types.h \
node/context.h \
+ node/eviction.h \
+ node/interface_ui.h \
+ node/mempool_args.h \
+ node/mempool_persist_args.h \
node/miner.h \
node/minisketchwrapper.h \
node/psbt.h \
node/transaction.h \
- node/interface_ui.h \
node/utxo_snapshot.h \
+ node/validation_cache_args.h \
noui.h \
outputtype.h \
policy/feerate.h \
policy/fees.h \
+ policy/fees_args.h \
policy/packages.h \
policy/policy.h \
policy/rbf.h \
@@ -253,9 +265,9 @@ BITCOIN_CORE_H = \
undo.h \
util/asmap.h \
util/bip32.h \
+ util/bitdeque.h \
util/bytevectorhash.h \
util/check.h \
- util/designator.h \
util/epochguard.h \
util/error.h \
util/fastrange.h \
@@ -271,6 +283,7 @@ BITCOIN_CORE_H = \
util/overloaded.h \
util/rbf.h \
util/readwritefile.h \
+ util/result.h \
util/serfloat.h \
util/settings.h \
util/sock.h \
@@ -336,7 +349,7 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
# Contains code accessing mempool and chain state that is meant to be separated
# from wallet and gui code (see node/README.md). Shared code should go in
# libbitcoin_common or libbitcoin_util libraries, instead.
-libbitcoin_node_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(NATPMP_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
+libbitcoin_node_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS) $(MINIUPNPC_CPPFLAGS) $(NATPMP_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
libbitcoin_node_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_node_a_SOURCES = \
addrdb.cpp \
@@ -349,6 +362,7 @@ libbitcoin_node_a_SOURCES = \
dbwrapper.cpp \
deploymentstatus.cpp \
flatfile.cpp \
+ headerssync.cpp \
httprpc.cpp \
httpserver.cpp \
i2p.cpp \
@@ -357,26 +371,34 @@ libbitcoin_node_a_SOURCES = \
index/coinstatsindex.cpp \
index/txindex.cpp \
init.cpp \
+ kernel/chain.cpp \
kernel/checks.cpp \
kernel/coinstats.cpp \
kernel/context.cpp \
+ kernel/mempool_persist.cpp \
mapport.cpp \
net.cpp \
- netgroup.cpp \
net_processing.cpp \
+ netgroup.cpp \
node/blockstorage.cpp \
node/caches.cpp \
node/chainstate.cpp \
node/coin.cpp \
+ node/connection_types.cpp \
node/context.cpp \
+ node/eviction.cpp \
+ node/interface_ui.cpp \
node/interfaces.cpp \
+ node/mempool_args.cpp \
+ node/mempool_persist_args.cpp \
node/miner.cpp \
node/minisketchwrapper.cpp \
node/psbt.cpp \
node/transaction.cpp \
- node/interface_ui.cpp \
+ node/validation_cache_args.cpp \
noui.cpp \
policy/fees.cpp \
+ policy/fees_args.cpp \
policy/packages.cpp \
policy/rbf.cpp \
policy/settings.cpp \
@@ -386,8 +408,8 @@ libbitcoin_node_a_SOURCES = \
rpc/fees.cpp \
rpc/mempool.cpp \
rpc/mining.cpp \
- rpc/node.cpp \
rpc/net.cpp \
+ rpc/node.cpp \
rpc/output_script.cpp \
rpc/rawtransaction.cpp \
rpc/server.cpp \
@@ -430,7 +452,7 @@ endif
# wallet: shared between bitcoind and bitcoin-qt, but only linked
# when wallet enabled
-libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BDB_CPPFLAGS) $(SQLITE_CFLAGS)
+libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS) $(BDB_CPPFLAGS) $(SQLITE_CFLAGS)
libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_wallet_a_SOURCES = \
wallet/coincontrol.cpp \
@@ -469,7 +491,7 @@ if USE_BDB
libbitcoin_wallet_a_SOURCES += wallet/bdb.cpp wallet/salvage.cpp
endif
-libbitcoin_wallet_tool_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+libbitcoin_wallet_tool_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
libbitcoin_wallet_tool_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_wallet_tool_a_SOURCES = \
wallet/wallettool.cpp \
@@ -633,7 +655,7 @@ libbitcoin_common_a_SOURCES = \
$(BITCOIN_CORE_H)
# util: shared between all executables.
-libbitcoin_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+libbitcoin_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
libbitcoin_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_util_a_SOURCES = \
support/lockedpool.cpp \
@@ -811,7 +833,7 @@ bitcoin_util_LDADD = \
# bitcoin-chainstate binary #
bitcoin_chainstate_SOURCES = bitcoin-chainstate.cpp
-bitcoin_chainstate_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+bitcoin_chainstate_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
bitcoin_chainstate_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
# $(LIBTOOL_APP_LDFLAGS) deliberately omitted here so that we can test linking
@@ -848,8 +870,7 @@ endif
# TODO: libbitcoinkernel is a work in progress consensus engine library, as more
# and more modules are decoupled from the consensus engine, this list will
-# shrink to only those which are absolutely necessary. For example, things
-# like index/*.cpp will be removed.
+# shrink to only those which are absolutely necessary.
libbitcoinkernel_la_SOURCES = \
kernel/bitcoinkernel.cpp \
arith_uint256.cpp \
@@ -869,9 +890,11 @@ libbitcoinkernel_la_SOURCES = \
flatfile.cpp \
fs.cpp \
hash.cpp \
+ kernel/chain.cpp \
kernel/checks.cpp \
kernel/coinstats.cpp \
kernel/context.cpp \
+ kernel/mempool_persist.cpp \
key.cpp \
logging.cpp \
node/blockstorage.cpp \
@@ -1045,6 +1068,15 @@ nodist_libbitcoin_ipc_a_SOURCES = $(libbitcoin_ipc_mpgen_output)
CLEANFILES += $(libbitcoin_ipc_mpgen_output)
endif
+%.raw.h: %.raw
+ @$(MKDIR_P) $(@D)
+ @{ \
+ echo "static unsigned const char $(*F)_raw[] = {" && \
+ $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
+ echo "};"; \
+ } > "$@.new" && mv -f "$@.new" "$@"
+ @echo "Generated $@"
+
include Makefile.minisketch.include
include Makefile.crc32c.include
@@ -1053,9 +1085,7 @@ include Makefile.leveldb.include
include Makefile.test_util.include
include Makefile.test_fuzz.include
-if ENABLE_TESTS
include Makefile.test.include
-endif
if ENABLE_BENCH
include Makefile.bench.include
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 532f668668..3ed643d932 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -27,6 +27,7 @@ bench_bench_bitcoin_SOURCES = \
bench/crypto_hash.cpp \
bench/data.cpp \
bench/data.h \
+ bench/descriptors.cpp \
bench/duplicate_inputs.cpp \
bench/examples.cpp \
bench/gcs_filter.cpp \
@@ -50,7 +51,7 @@ bench_bench_bitcoin_SOURCES = \
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_BENCH_FILES)
-bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
+bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
bench_bench_bitcoin_LDADD = \
$(LIBTEST_UTIL) \
@@ -93,12 +94,3 @@ bench: $(BENCH_BINARY) FORCE
bitcoin_bench_clean : FORCE
rm -f $(CLEAN_BITCOIN_BENCH) $(bench_bench_bitcoin_OBJECTS) $(BENCH_BINARY)
-
-%.raw.h: %.raw
- @$(MKDIR_P) $(@D)
- @{ \
- echo "static unsigned const char $(*F)_raw[] = {" && \
- $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
- echo "};"; \
- } > "$@.new" && mv -f "$@.new" "$@"
- @echo "Generated $@"
diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include
index 066f8940c5..bf14fe206b 100644
--- a/src/Makefile.leveldb.include
+++ b/src/Makefile.leveldb.include
@@ -13,7 +13,6 @@ LIBMEMENV = $(LIBMEMENV_INT)
LEVELDB_CPPFLAGS =
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
-LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
LEVELDB_CPPFLAGS_INT =
LEVELDB_CPPFLAGS_INT += -I$(srcdir)/leveldb
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index b4acc47aa1..602a118259 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -295,7 +295,7 @@ BITCOIN_QT_RC = qt/res/bitcoin-qt-res.rc
BITCOIN_QT_INCLUDES = -DQT_NO_KEYWORDS -DQT_USE_QSTRINGBUILDER
qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
- $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(QR_CFLAGS)
+ $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(QR_CFLAGS) $(BOOST_CPPFLAGS)
qt_libbitcoinqt_a_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS)
qt_libbitcoinqt_a_OBJCXXFLAGS = $(AM_OBJCXXFLAGS) $(QT_PIE_FLAGS)
diff --git a/src/Makefile.qt_locale.include b/src/Makefile.qt_locale.include
index 8638bd024c..3ccbc4fd18 100644
--- a/src/Makefile.qt_locale.include
+++ b/src/Makefile.qt_locale.include
@@ -18,7 +18,6 @@ QT_TS = \
qt/locale/bitcoin_es_CL.ts \
qt/locale/bitcoin_es_CO.ts \
qt/locale/bitcoin_es_DO.ts \
- qt/locale/bitcoin_es_MX.ts \
qt/locale/bitcoin_es_VE.ts \
qt/locale/bitcoin_et.ts \
qt/locale/bitcoin_eu.ts \
@@ -31,6 +30,7 @@ QT_TS = \
qt/locale/bitcoin_gl.ts \
qt/locale/bitcoin_gl_ES.ts \
qt/locale/bitcoin_gu.ts \
+ qt/locale/bitcoin_ha.ts \
qt/locale/bitcoin_he.ts \
qt/locale/bitcoin_hr.ts \
qt/locale/bitcoin_hu.ts \
@@ -43,6 +43,7 @@ QT_TS = \
qt/locale/bitcoin_kl.ts \
qt/locale/bitcoin_km.ts \
qt/locale/bitcoin_ko.ts \
+ qt/locale/bitcoin_ku.ts \
qt/locale/bitcoin_ku_IQ.ts \
qt/locale/bitcoin_ky.ts \
qt/locale/bitcoin_la.ts \
@@ -58,6 +59,7 @@ QT_TS = \
qt/locale/bitcoin_ne.ts \
qt/locale/bitcoin_nl.ts \
qt/locale/bitcoin_no.ts \
+ qt/locale/bitcoin_pa.ts \
qt/locale/bitcoin_pam.ts \
qt/locale/bitcoin_pl.ts \
qt/locale/bitcoin_pt.ts \
@@ -78,10 +80,13 @@ QT_TS = \
qt/locale/bitcoin_ta.ts \
qt/locale/bitcoin_te.ts \
qt/locale/bitcoin_th.ts \
+ qt/locale/bitcoin_tk.ts \
+ qt/locale/bitcoin_tl.ts \
qt/locale/bitcoin_tr.ts \
qt/locale/bitcoin_ug.ts \
qt/locale/bitcoin_uk.ts \
qt/locale/bitcoin_ur.ts \
+ qt/locale/bitcoin_uz.ts \
qt/locale/bitcoin_uz@Cyrl.ts \
qt/locale/bitcoin_uz@Latn.ts \
qt/locale/bitcoin_vi.ts \
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index fa822f2954..89c659d4b9 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -27,7 +27,7 @@ TEST_QT_H = \
qt/test/wallettests.h
qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \
- $(QT_INCLUDES) $(QT_TEST_INCLUDES)
+ $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(BOOST_CPPFLAGS)
qt_test_test_bitcoin_qt_SOURCES = \
init/bitcoin-qt.cpp \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index ebd9e860cf..5f2e535e85 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -6,7 +6,7 @@ if ENABLE_FUZZ_BINARY
noinst_PROGRAMS += test/fuzz/fuzz
endif
-if !ENABLE_FUZZ
+if ENABLE_TESTS
bin_PROGRAMS += test/test_bitcoin
endif
@@ -93,6 +93,7 @@ BITCOIN_TESTS =\
test/fs_tests.cpp \
test/getarg_tests.cpp \
test/hash_tests.cpp \
+ test/headers_sync_chainwork_tests.cpp \
test/httpserver_tests.cpp \
test/i2p_tests.cpp \
test/interfaces_tests.cpp \
@@ -117,7 +118,9 @@ BITCOIN_TESTS =\
test/prevector_tests.cpp \
test/raii_event_tests.cpp \
test/random_tests.cpp \
+ test/rbf_tests.cpp \
test/rest_tests.cpp \
+ test/result_tests.cpp \
test/reverselock_tests.cpp \
test/rpc_tests.cpp \
test/sanity_tests.cpp \
@@ -160,6 +163,7 @@ BITCOIN_TESTS =\
if ENABLE_WALLET
BITCOIN_TESTS += \
+ wallet/test/feebumper_tests.cpp \
wallet/test/psbt_wallet_tests.cpp \
wallet/test/spend_tests.cpp \
wallet/test/wallet_tests.cpp \
@@ -167,9 +171,11 @@ BITCOIN_TESTS += \
wallet/test/wallet_crypto_tests.cpp \
wallet/test/wallet_transaction_tests.cpp \
wallet/test/coinselector_tests.cpp \
+ wallet/test/availablecoins_tests.cpp \
wallet/test/init_tests.cpp \
wallet/test/ismine_tests.cpp \
- wallet/test/scriptpubkeyman_tests.cpp
+ wallet/test/scriptpubkeyman_tests.cpp \
+ wallet/test/walletload_tests.cpp
FUZZ_SUITE_LD_COMMON +=\
$(SQLITE_LIBS) \
@@ -197,7 +203,7 @@ BITCOIN_TEST_SUITE += \
endif # ENABLE_WALLET
test_test_bitcoin_SOURCES = $(BITCOIN_TEST_SUITE) $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
-test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(TESTDEFS) $(EVENT_CFLAGS)
+test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(TESTDEFS) $(BOOST_CPPFLAGS) $(EVENT_CFLAGS)
test_test_bitcoin_LDADD = $(LIBTEST_UTIL)
if ENABLE_WALLET
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
@@ -217,7 +223,7 @@ FUZZ_SUITE_LD_COMMON += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
if ENABLE_FUZZ_BINARY
-test_fuzz_fuzz_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_fuzz_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
test_fuzz_fuzz_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_fuzz_fuzz_LDADD = $(FUZZ_SUITE_LD_COMMON)
test_fuzz_fuzz_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) $(RUNTIME_LDFLAGS)
@@ -231,6 +237,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/banman.cpp \
test/fuzz/base_encode_decode.cpp \
test/fuzz/bech32.cpp \
+ test/fuzz/bitdeque.cpp \
test/fuzz/block.cpp \
test/fuzz/block_header.cpp \
test/fuzz/blockfilter.cpp \
@@ -325,6 +332,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/tx_in.cpp \
test/fuzz/tx_out.cpp \
test/fuzz/tx_pool.cpp \
+ test/fuzz/txorphan.cpp \
test/fuzz/txrequest.cpp \
test/fuzz/utxo_snapshot.cpp \
test/fuzz/validation_load_mempool.cpp \
@@ -335,7 +343,7 @@ nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
-CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno test/fuzz/*.gcda test/fuzz/*.gcno test/util/*.gcda test/util/*.gcno $(GENERATED_TEST_FILES) $(BITCOIN_TESTS:=.log)
+CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno test/fuzz/*.gcda test/fuzz/*.gcno test/util/*.gcda test/util/*.gcno $(GENERATED_TEST_FILES) $(addsuffix .log,$(basename $(BITCOIN_TESTS)))
CLEANFILES += $(CLEAN_BITCOIN_TEST)
@@ -371,8 +379,8 @@ endif
endif
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
-if !ENABLE_FUZZ
-UNIVALUE_TESTS = univalue/test/object univalue/test/unitester univalue/test/no_nul
+if ENABLE_TESTS
+UNIVALUE_TESTS = univalue/test/object univalue/test/unitester
noinst_PROGRAMS += $(UNIVALUE_TESTS)
TESTS += $(UNIVALUE_TESTS)
@@ -381,11 +389,6 @@ univalue_test_unitester_LDADD = $(LIBUNIVALUE)
univalue_test_unitester_CPPFLAGS = -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) -DJSON_TEST_SRC=\"$(srcdir)/$(UNIVALUE_TEST_DATA_DIR_INT)\"
univalue_test_unitester_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS)
-univalue_test_no_nul_SOURCES = $(UNIVALUE_TEST_NO_NUL_INT)
-univalue_test_no_nul_LDADD = $(LIBUNIVALUE)
-univalue_test_no_nul_CPPFLAGS = -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT)
-univalue_test_no_nul_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS)
-
univalue_test_object_SOURCES = $(UNIVALUE_TEST_OBJECT_INT)
univalue_test_object_LDADD = $(LIBUNIVALUE)
univalue_test_object_CPPFLAGS = -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT)
@@ -416,12 +419,3 @@ endif
echo "};};"; \
} > "$@.new" && mv -f "$@.new" "$@"
@echo "Generated $@"
-
-%.raw.h: %.raw
- @$(MKDIR_P) $(@D)
- @{ \
- echo "static unsigned const char $(*F)_raw[] = {" && \
- $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
- echo "};"; \
- } > "$@.new" && mv -f "$@.new" "$@"
- @echo "Generated $@"
diff --git a/src/Makefile.test_fuzz.include b/src/Makefile.test_fuzz.include
index 8922dda3ad..11b5c12062 100644
--- a/src/Makefile.test_fuzz.include
+++ b/src/Makefile.test_fuzz.include
@@ -10,9 +10,10 @@ EXTRA_LIBRARIES += \
TEST_FUZZ_H = \
test/fuzz/fuzz.h \
test/fuzz/FuzzedDataProvider.h \
+ test/fuzz/mempool_utils.h \
test/fuzz/util.h
-libtest_fuzz_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(NATPMP_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
+libtest_fuzz_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
libtest_fuzz_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libtest_fuzz_a_SOURCES = \
test/fuzz/fuzz.cpp \
diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include
index 9306bb6fcc..ada789f1b0 100644
--- a/src/Makefile.test_util.include
+++ b/src/Makefile.test_util.include
@@ -20,7 +20,7 @@ TEST_UTIL_H = \
test/util/validation.h \
test/util/wallet.h
-libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(NATPMP_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
+libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BOOST_CPPFLAGS)
libtest_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libtest_util_a_SOURCES = \
test/util/blockfilter.cpp \
diff --git a/src/addrdb.cpp b/src/addrdb.cpp
index 31f8eadf98..7106d819b0 100644
--- a/src/addrdb.cpp
+++ b/src/addrdb.cpp
@@ -187,11 +187,11 @@ std::optional<bilingual_str> LoadAddrman(const NetGroupManager& netgroupman, con
auto check_addrman = std::clamp<int32_t>(args.GetIntArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, 1000000);
addrman = std::make_unique<AddrMan>(netgroupman, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
- int64_t nStart = GetTimeMillis();
+ const auto start{SteadyClock::now()};
const auto path_addr{args.GetDataDirNet() / "peers.dat"};
try {
DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
- LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), GetTimeMillis() - nStart);
+ LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
} catch (const DbNotFoundError&) {
// Addrman can be in an inconsistent state after failure, reset it
addrman = std::make_unique<AddrMan>(netgroupman, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 204bb544c5..f16ff2230b 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -14,10 +14,10 @@
#include <random.h>
#include <serialize.h>
#include <streams.h>
-#include <timedata.h>
#include <tinyformat.h>
#include <uint256.h>
#include <util/check.h>
+#include <util/time.h>
#include <cmath>
#include <optional>
@@ -29,19 +29,19 @@ static constexpr uint32_t ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP{64};
/** Maximum number of times an address can occur in the new table */
static constexpr int32_t ADDRMAN_NEW_BUCKETS_PER_ADDRESS{8};
/** How old addresses can maximally be */
-static constexpr int64_t ADDRMAN_HORIZON_DAYS{30};
+static constexpr auto ADDRMAN_HORIZON{30 * 24h};
/** After how many failed attempts we give up on a new node */
static constexpr int32_t ADDRMAN_RETRIES{3};
/** How many successive failures are allowed ... */
static constexpr int32_t ADDRMAN_MAX_FAILURES{10};
-/** ... in at least this many days */
-static constexpr int64_t ADDRMAN_MIN_FAIL_DAYS{7};
+/** ... in at least this duration */
+static constexpr auto ADDRMAN_MIN_FAIL{7 * 24h};
/** How recent a successful connection should be before we allow an address to be evicted from tried */
-static constexpr int64_t ADDRMAN_REPLACEMENT_HOURS{4};
+static constexpr auto ADDRMAN_REPLACEMENT{4h};
/** The maximum number of tried addr collisions to store */
static constexpr size_t ADDRMAN_SET_TRIED_COLLISION_SIZE{10};
-/** The maximum time we'll spend trying to resolve a tried table collision, in seconds */
-static constexpr int64_t ADDRMAN_TEST_WINDOW{40*60}; // 40 minutes
+/** The maximum time we'll spend trying to resolve a tried table collision */
+static constexpr auto ADDRMAN_TEST_WINDOW{40min};
int AddrInfo::GetTriedBucket(const uint256& nKey, const NetGroupManager& netgroupman) const
{
@@ -64,36 +64,39 @@ int AddrInfo::GetBucketPosition(const uint256& nKey, bool fNew, int nBucket) con
return hash1 % ADDRMAN_BUCKET_SIZE;
}
-bool AddrInfo::IsTerrible(int64_t nNow) const
+bool AddrInfo::IsTerrible(NodeSeconds now) const
{
- if (nNow - nLastTry <= 60) { // never remove things tried in the last minute
+ if (now - m_last_try <= 1min) { // never remove things tried in the last minute
return false;
}
- if (nTime > nNow + 10 * 60) // came in a flying DeLorean
+ if (nTime > now + 10min) { // came in a flying DeLorean
return true;
+ }
- if (nNow - nTime > ADDRMAN_HORIZON_DAYS * 24 * 60 * 60) { // not seen in recent history
+ if (now - nTime > ADDRMAN_HORIZON) { // not seen in recent history
return true;
}
- if (nLastSuccess == 0 && nAttempts >= ADDRMAN_RETRIES) // tried N times and never a success
+ if (TicksSinceEpoch<std::chrono::seconds>(m_last_success) == 0 && nAttempts >= ADDRMAN_RETRIES) { // tried N times and never a success
return true;
+ }
- if (nNow - nLastSuccess > ADDRMAN_MIN_FAIL_DAYS * 24 * 60 * 60 && nAttempts >= ADDRMAN_MAX_FAILURES) // N successive failures in the last week
+ if (now - m_last_success > ADDRMAN_MIN_FAIL && nAttempts >= ADDRMAN_MAX_FAILURES) { // N successive failures in the last week
return true;
+ }
return false;
}
-double AddrInfo::GetChance(int64_t nNow) const
+double AddrInfo::GetChance(NodeSeconds now) const
{
double fChance = 1.0;
- int64_t nSinceLastTry = std::max<int64_t>(nNow - nLastTry, 0);
// deprioritize very recent attempts away
- if (nSinceLastTry < 60 * 10)
+ if (now - m_last_try < 10min) {
fChance *= 0.01;
+ }
// deprioritize 66% after each failed attempt, but at most 1/28th to avoid the search taking forever or overly penalizing outages.
fChance *= pow(0.66, std::min(nAttempts, 8));
@@ -540,7 +543,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
info.fInTried = true;
}
-bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
+bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, std::chrono::seconds time_penalty)
{
AssertLockHeld(cs);
@@ -552,15 +555,15 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
// Do not set a penalty for a source's self-announcement
if (addr == source) {
- nTimePenalty = 0;
+ time_penalty = 0s;
}
if (pinfo) {
// periodically update nTime
- bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
- int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
- if (pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty) {
- pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty);
+ const bool currently_online{NodeClock::now() - addr.nTime < 24h};
+ const auto update_interval{currently_online ? 1h : 24h};
+ if (pinfo->nTime < addr.nTime - update_interval - time_penalty) {
+ pinfo->nTime = std::max(NodeSeconds{0s}, addr.nTime - time_penalty);
}
// add services
@@ -587,7 +590,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
return false;
} else {
pinfo = Create(addr, source, &nId);
- pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
+ pinfo->nTime = std::max(NodeSeconds{0s}, pinfo->nTime - time_penalty);
nNew++;
}
@@ -617,13 +620,13 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
return fInsert;
}
-bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nTime)
+bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, NodeSeconds time)
{
AssertLockHeld(cs);
int nId;
- nLastGood = nTime;
+ m_last_good = time;
AddrInfo* pinfo = Find(addr, &nId);
@@ -633,8 +636,8 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
AddrInfo& info = *pinfo;
// update info
- info.nLastSuccess = nTime;
- info.nLastTry = nTime;
+ info.m_last_success = time;
+ info.m_last_try = time;
info.nAttempts = 0;
// nTime is not updated here, to avoid leaking information about
// currently-connected peers.
@@ -671,11 +674,11 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
}
}
-bool AddrManImpl::Add_(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty)
+bool AddrManImpl::Add_(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
{
int added{0};
for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) {
- added += AddSingle(*it, source, nTimePenalty) ? 1 : 0;
+ added += AddSingle(*it, source, time_penalty) ? 1 : 0;
}
if (added > 0) {
LogPrint(BCLog::ADDRMAN, "Added %i addresses (of %i) from %s: %i tried, %i new\n", added, vAddr.size(), source.ToString(), nTried, nNew);
@@ -683,7 +686,7 @@ bool AddrManImpl::Add_(const std::vector<CAddress> &vAddr, const CNetAddr& sourc
return added > 0;
}
-void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime)
+void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, NodeSeconds time)
{
AssertLockHeld(cs);
@@ -696,14 +699,14 @@ void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, int64_t nTi
AddrInfo& info = *pinfo;
// update info
- info.nLastTry = nTime;
- if (fCountFailure && info.nLastCountAttempt < nLastGood) {
- info.nLastCountAttempt = nTime;
+ info.m_last_try = time;
+ if (fCountFailure && info.m_last_count_attempt < m_last_good) {
+ info.m_last_count_attempt = time;
info.nAttempts++;
}
}
-std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const
+std::pair<CAddress, NodeSeconds> AddrManImpl::Select_(bool newOnly) const
{
AssertLockHeld(cs);
@@ -736,7 +739,7 @@ std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const
// With probability GetChance() * fChanceFactor, return the entry.
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) {
LogPrint(BCLog::ADDRMAN, "Selected %s from tried\n", info.ToString());
- return {info, info.nLastTry};
+ return {info, info.m_last_try};
}
// Otherwise start over with a (likely) different bucket, and increased chance factor.
fChanceFactor *= 1.2;
@@ -764,7 +767,7 @@ std::pair<CAddress, int64_t> AddrManImpl::Select_(bool newOnly) const
// With probability GetChance() * fChanceFactor, return the entry.
if (insecure_rand.randbits(30) < fChanceFactor * info.GetChance() * (1 << 30)) {
LogPrint(BCLog::ADDRMAN, "Selected %s from new\n", info.ToString());
- return {info, info.nLastTry};
+ return {info, info.m_last_try};
}
// Otherwise start over with a (likely) different bucket, and increased chance factor.
fChanceFactor *= 1.2;
@@ -785,7 +788,7 @@ std::vector<CAddress> AddrManImpl::GetAddr_(size_t max_addresses, size_t max_pct
}
// gather a list of random nodes, skipping those of low quality
- const int64_t now{GetAdjustedTime()};
+ const auto now{Now<NodeSeconds>()};
std::vector<CAddress> addresses;
for (unsigned int n = 0; n < vRandom.size(); n++) {
if (addresses.size() >= nNodes)
@@ -810,7 +813,7 @@ std::vector<CAddress> AddrManImpl::GetAddr_(size_t max_addresses, size_t max_pct
return addresses;
}
-void AddrManImpl::Connected_(const CService& addr, int64_t nTime)
+void AddrManImpl::Connected_(const CService& addr, NodeSeconds time)
{
AssertLockHeld(cs);
@@ -823,9 +826,10 @@ void AddrManImpl::Connected_(const CService& addr, int64_t nTime)
AddrInfo& info = *pinfo;
// update info
- int64_t nUpdateInterval = 20 * 60;
- if (nTime - info.nTime > nUpdateInterval)
- info.nTime = nTime;
+ const auto update_interval{20min};
+ if (time - info.nTime > update_interval) {
+ info.nTime = time;
+ }
}
void AddrManImpl::SetServices_(const CService& addr, ServiceFlags nServices)
@@ -870,22 +874,22 @@ void AddrManImpl::ResolveCollisions_()
int id_old = vvTried[tried_bucket][tried_bucket_pos];
AddrInfo& info_old = mapInfo[id_old];
- const auto current_time{GetAdjustedTime()};
+ const auto current_time{Now<NodeSeconds>()};
// Has successfully connected in last X hours
- if (current_time - info_old.nLastSuccess < ADDRMAN_REPLACEMENT_HOURS*(60*60)) {
+ if (current_time - info_old.m_last_success < ADDRMAN_REPLACEMENT) {
erase_collision = true;
- } else if (current_time - info_old.nLastTry < ADDRMAN_REPLACEMENT_HOURS*(60*60)) { // attempted to connect and failed in last X hours
+ } else if (current_time - info_old.m_last_try < ADDRMAN_REPLACEMENT) { // attempted to connect and failed in last X hours
// Give address at least 60 seconds to successfully connect
- if (current_time - info_old.nLastTry > 60) {
+ if (current_time - info_old.m_last_try > 60s) {
LogPrint(BCLog::ADDRMAN, "Replacing %s with %s in tried table\n", info_old.ToString(), info_new.ToString());
// Replaces an existing address already in the tried table with the new address
Good_(info_new, false, current_time);
erase_collision = true;
}
- } else if (current_time - info_new.nLastSuccess > ADDRMAN_TEST_WINDOW) {
+ } else if (current_time - info_new.m_last_success > ADDRMAN_TEST_WINDOW) {
// If the collision hasn't resolved in some reasonable amount of time,
// just evict the old entry -- we must not be able to
// connect to it for some reason.
@@ -894,7 +898,7 @@ void AddrManImpl::ResolveCollisions_()
erase_collision = true;
}
} else { // Collision is not actually a collision anymore
- Good_(info_new, false, GetAdjustedTime());
+ Good_(info_new, false, Now<NodeSeconds>());
erase_collision = true;
}
}
@@ -907,7 +911,7 @@ void AddrManImpl::ResolveCollisions_()
}
}
-std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision_()
+std::pair<CAddress, NodeSeconds> AddrManImpl::SelectTriedCollision_()
{
AssertLockHeld(cs);
@@ -932,7 +936,7 @@ std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision_()
int tried_bucket_pos = newInfo.GetBucketPosition(nKey, false, tried_bucket);
const AddrInfo& info_old = mapInfo[vvTried[tried_bucket][tried_bucket_pos]];
- return {info_old, info_old.nLastTry};
+ return {info_old, info_old.m_last_try};
}
std::optional<AddressPosition> AddrManImpl::FindAddressEntry_(const CAddress& addr)
@@ -990,8 +994,9 @@ int AddrManImpl::CheckAddrman() const
int n = entry.first;
const AddrInfo& info = entry.second;
if (info.fInTried) {
- if (!info.nLastSuccess)
+ if (!TicksSinceEpoch<std::chrono::seconds>(info.m_last_success)) {
return -1;
+ }
if (info.nRefCount)
return -2;
setTried.insert(n);
@@ -1008,10 +1013,12 @@ int AddrManImpl::CheckAddrman() const
}
if (info.nRandomPos < 0 || (size_t)info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n)
return -14;
- if (info.nLastTry < 0)
+ if (info.m_last_try < NodeSeconds{0s}) {
return -6;
- if (info.nLastSuccess < 0)
+ }
+ if (info.m_last_success < NodeSeconds{0s}) {
return -8;
+ }
}
if (setTried.size() != (size_t)nTried)
@@ -1067,29 +1074,29 @@ size_t AddrManImpl::size() const
return vRandom.size();
}
-bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
+bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
{
LOCK(cs);
Check();
- auto ret = Add_(vAddr, source, nTimePenalty);
+ auto ret = Add_(vAddr, source, time_penalty);
Check();
return ret;
}
-bool AddrManImpl::Good(const CService& addr, int64_t nTime)
+bool AddrManImpl::Good(const CService& addr, NodeSeconds time)
{
LOCK(cs);
Check();
- auto ret = Good_(addr, /*test_before_evict=*/true, nTime);
+ auto ret = Good_(addr, /*test_before_evict=*/true, time);
Check();
return ret;
}
-void AddrManImpl::Attempt(const CService& addr, bool fCountFailure, int64_t nTime)
+void AddrManImpl::Attempt(const CService& addr, bool fCountFailure, NodeSeconds time)
{
LOCK(cs);
Check();
- Attempt_(addr, fCountFailure, nTime);
+ Attempt_(addr, fCountFailure, time);
Check();
}
@@ -1101,7 +1108,7 @@ void AddrManImpl::ResolveCollisions()
Check();
}
-std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision()
+std::pair<CAddress, NodeSeconds> AddrManImpl::SelectTriedCollision()
{
LOCK(cs);
Check();
@@ -1110,7 +1117,7 @@ std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision()
return ret;
}
-std::pair<CAddress, int64_t> AddrManImpl::Select(bool newOnly) const
+std::pair<CAddress, NodeSeconds> AddrManImpl::Select(bool newOnly) const
{
LOCK(cs);
Check();
@@ -1128,11 +1135,11 @@ std::vector<CAddress> AddrManImpl::GetAddr(size_t max_addresses, size_t max_pct,
return addresses;
}
-void AddrManImpl::Connected(const CService& addr, int64_t nTime)
+void AddrManImpl::Connected(const CService& addr, NodeSeconds time)
{
LOCK(cs);
Check();
- Connected_(addr, nTime);
+ Connected_(addr, time);
Check();
}
@@ -1184,19 +1191,19 @@ size_t AddrMan::size() const
return m_impl->size();
}
-bool AddrMan::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
+bool AddrMan::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
{
- return m_impl->Add(vAddr, source, nTimePenalty);
+ return m_impl->Add(vAddr, source, time_penalty);
}
-bool AddrMan::Good(const CService& addr, int64_t nTime)
+bool AddrMan::Good(const CService& addr, NodeSeconds time)
{
- return m_impl->Good(addr, nTime);
+ return m_impl->Good(addr, time);
}
-void AddrMan::Attempt(const CService& addr, bool fCountFailure, int64_t nTime)
+void AddrMan::Attempt(const CService& addr, bool fCountFailure, NodeSeconds time)
{
- m_impl->Attempt(addr, fCountFailure, nTime);
+ m_impl->Attempt(addr, fCountFailure, time);
}
void AddrMan::ResolveCollisions()
@@ -1204,12 +1211,12 @@ void AddrMan::ResolveCollisions()
m_impl->ResolveCollisions();
}
-std::pair<CAddress, int64_t> AddrMan::SelectTriedCollision()
+std::pair<CAddress, NodeSeconds> AddrMan::SelectTriedCollision()
{
return m_impl->SelectTriedCollision();
}
-std::pair<CAddress, int64_t> AddrMan::Select(bool newOnly) const
+std::pair<CAddress, NodeSeconds> AddrMan::Select(bool newOnly) const
{
return m_impl->Select(newOnly);
}
@@ -1219,9 +1226,9 @@ std::vector<CAddress> AddrMan::GetAddr(size_t max_addresses, size_t max_pct, std
return m_impl->GetAddr(max_addresses, max_pct, network);
}
-void AddrMan::Connected(const CService& addr, int64_t nTime)
+void AddrMan::Connected(const CService& addr, NodeSeconds time)
{
- m_impl->Connected(addr, nTime);
+ m_impl->Connected(addr, time);
}
void AddrMan::SetServices(const CService& addr, ServiceFlags nServices)
diff --git a/src/addrman.h b/src/addrman.h
index a0063e8a9c..5099c8c7a3 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -10,7 +10,7 @@
#include <netgroup.h>
#include <protocol.h>
#include <streams.h>
-#include <timedata.h>
+#include <util/time.h>
#include <cstdint>
#include <memory>
@@ -107,23 +107,23 @@ public:
*
* @param[in] vAddr Address records to attempt to add.
* @param[in] source The address of the node that sent us these addr records.
- * @param[in] nTimePenalty A "time penalty" to apply to the address record's nTime. If a peer
+ * @param[in] time_penalty A "time penalty" to apply to the address record's nTime. If a peer
* sends us an address record with nTime=n, then we'll add it to our
- * addrman with nTime=(n - nTimePenalty).
+ * addrman with nTime=(n - time_penalty).
* @return true if at least one address is successfully added. */
- bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty = 0);
+ bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty = 0s);
/**
* Mark an address record as accessible and attempt to move it to addrman's tried table.
*
* @param[in] addr Address record to attempt to move to tried table.
- * @param[in] nTime The time that we were last connected to this peer.
+ * @param[in] time The time that we were last connected to this peer.
* @return true if the address is successfully moved from the new table to the tried table.
*/
- bool Good(const CService& addr, int64_t nTime = GetAdjustedTime());
+ bool Good(const CService& addr, NodeSeconds time = Now<NodeSeconds>());
//! Mark an entry as connection attempted to.
- void Attempt(const CService& addr, bool fCountFailure, int64_t nTime = GetAdjustedTime());
+ void Attempt(const CService& addr, bool fCountFailure, NodeSeconds time = Now<NodeSeconds>());
//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
void ResolveCollisions();
@@ -133,18 +133,18 @@ public:
* attempting to evict.
*
* @return CAddress The record for the selected tried peer.
- * int64_t The last time we attempted to connect to that peer.
+ * seconds The last time we attempted to connect to that peer.
*/
- std::pair<CAddress, int64_t> SelectTriedCollision();
+ std::pair<CAddress, NodeSeconds> SelectTriedCollision();
/**
* Choose an address to connect to.
*
* @param[in] newOnly Whether to only select addresses from the new table.
* @return CAddress The record for the selected peer.
- * int64_t The last time we attempted to connect to that peer.
+ * seconds The last time we attempted to connect to that peer.
*/
- std::pair<CAddress, int64_t> Select(bool newOnly = false) const;
+ std::pair<CAddress, NodeSeconds> Select(bool newOnly = false) const;
/**
* Return all or many randomly selected addresses, optionally by network.
@@ -166,9 +166,9 @@ public:
* not leak information about currently connected peers.
*
* @param[in] addr The address of the peer we were connected to
- * @param[in] nTime The time that we were last connected to this peer
+ * @param[in] time The time that we were last connected to this peer
*/
- void Connected(const CService& addr, int64_t nTime = GetAdjustedTime());
+ void Connected(const CService& addr, NodeSeconds time = Now<NodeSeconds>());
//! Update an entry's service bits.
void SetServices(const CService& addr, ServiceFlags nServices);
diff --git a/src/addrman_impl.h b/src/addrman_impl.h
index 9d98cdde54..376e79f49f 100644
--- a/src/addrman_impl.h
+++ b/src/addrman_impl.h
@@ -11,7 +11,9 @@
#include <protocol.h>
#include <serialize.h>
#include <sync.h>
+#include <timedata.h>
#include <uint256.h>
+#include <util/time.h>
#include <cstdint>
#include <optional>
@@ -38,16 +40,16 @@ class AddrInfo : public CAddress
{
public:
//! last try whatsoever by us (memory only)
- int64_t nLastTry{0};
+ NodeSeconds m_last_try{0s};
//! last counted attempt (memory only)
- int64_t nLastCountAttempt{0};
+ NodeSeconds m_last_count_attempt{0s};
//! where knowledge about this address first came from
CNetAddr source;
//! last successful connection by us
- int64_t nLastSuccess{0};
+ NodeSeconds m_last_success{0s};
//! connection attempts since last successful attempt
int nAttempts{0};
@@ -64,7 +66,7 @@ public:
SERIALIZE_METHODS(AddrInfo, obj)
{
READWRITEAS(CAddress, obj);
- READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
+ READWRITE(obj.source, Using<ChronoFormatter<int64_t>>(obj.m_last_success), obj.nAttempts);
}
AddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
@@ -91,10 +93,10 @@ public:
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
//! Determine whether the statistics about this entry are bad enough so that it can just be deleted
- bool IsTerrible(int64_t nNow = GetAdjustedTime()) const;
+ bool IsTerrible(NodeSeconds now = Now<NodeSeconds>()) const;
//! Calculate the relative chance this entry should be given when selecting nodes to connect to
- double GetChance(int64_t nNow = GetAdjustedTime()) const;
+ double GetChance(NodeSeconds now = Now<NodeSeconds>()) const;
};
class AddrManImpl
@@ -112,26 +114,26 @@ public:
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
- bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
+ bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
- bool Good(const CService& addr, int64_t nTime)
+ bool Good(const CService& addr, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
- void Attempt(const CService& addr, bool fCountFailure, int64_t nTime)
+ void Attempt(const CService& addr, bool fCountFailure, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs);
- std::pair<CAddress, int64_t> SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
+ std::pair<CAddress, NodeSeconds> SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
- std::pair<CAddress, int64_t> Select(bool newOnly) const
+ std::pair<CAddress, NodeSeconds> Select(bool newOnly) const
EXCLUSIVE_LOCKS_REQUIRED(!cs);
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
EXCLUSIVE_LOCKS_REQUIRED(!cs);
- void Connected(const CService& addr, int64_t nTime)
+ void Connected(const CService& addr, NodeSeconds time)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
void SetServices(const CService& addr, ServiceFlags nServices)
@@ -202,7 +204,7 @@ private:
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
//! last time Good was called (memory only). Initially set to 1 so that "never" is strictly worse.
- int64_t nLastGood GUARDED_BY(cs){1};
+ NodeSeconds m_last_good GUARDED_BY(cs){1s};
//! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
std::set<int> m_tried_collisions;
@@ -233,25 +235,25 @@ private:
/** Attempt to add a single address to addrman's new table.
* @see AddrMan::Add() for parameters. */
- bool AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ bool AddSingle(const CAddress& addr, const CNetAddr& source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
- bool Good_(const CService& addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ bool Good_(const CService& addr, bool test_before_evict, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
- bool Add_(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ bool Add_(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
- void Attempt_(const CService& addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void Attempt_(const CService& addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
- std::pair<CAddress, int64_t> Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);
+ std::pair<CAddress, NodeSeconds> Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);
std::vector<CAddress> GetAddr_(size_t max_addresses, size_t max_pct, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);
- void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ void Connected_(const CService& addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs);
void SetServices_(const CService& addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
- std::pair<CAddress, int64_t> SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
+ std::pair<CAddress, NodeSeconds> SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
std::optional<AddressPosition> FindAddressEntry_(const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(cs);
diff --git a/src/banman.cpp b/src/banman.cpp
index 508383d9f2..3cd646c148 100644
--- a/src/banman.cpp
+++ b/src/banman.cpp
@@ -31,12 +31,12 @@ void BanMan::LoadBanlist()
if (m_client_interface) m_client_interface->InitMessage(_("Loading banlist…").translated);
- int64_t n_start = GetTimeMillis();
+ const auto start{SteadyClock::now()};
if (m_ban_db.Read(m_banned)) {
SweepBanned(); // sweep out unused entries
LogPrint(BCLog::NET, "Loaded %d banned node addresses/subnets %dms\n", m_banned.size(),
- GetTimeMillis() - n_start);
+ Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
} else {
LogPrintf("Recreating the banlist database\n");
m_banned = {};
@@ -58,13 +58,13 @@ void BanMan::DumpBanlist()
SetBannedSetDirty(false);
}
- int64_t n_start = GetTimeMillis();
+ const auto start{SteadyClock::now()};
if (!m_ban_db.Write(banmap)) {
SetBannedSetDirty(true);
}
LogPrint(BCLog::NET, "Flushed %d banned node addresses/subnets to disk %dms\n", banmap.size(),
- GetTimeMillis() - n_start);
+ Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
}
void BanMan::ClearBanned()
diff --git a/src/bench/addrman.cpp b/src/bench/addrman.cpp
index 76300f4db8..f14d1f89b6 100644
--- a/src/bench/addrman.cpp
+++ b/src/bench/addrman.cpp
@@ -43,7 +43,7 @@ static void CreateAddresses()
CAddress ret(CService(addr, port), NODE_NETWORK);
- ret.nTime = GetAdjustedTime();
+ ret.nTime = Now<NodeSeconds>();
return ret;
};
diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp
index 52e5cb743f..53aa470042 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -8,6 +8,7 @@
#include <chainparams.h>
#include <consensus/validation.h>
#include <streams.h>
+#include <util/system.h>
#include <validation.h>
// These are the two major time-sinks which happen after we have fully received
diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp
index b2958bcc9f..6ada28115e 100644
--- a/src/bench/coin_selection.cpp
+++ b/src/bench/coin_selection.cpp
@@ -56,9 +56,10 @@ static void CoinSelection(benchmark::Bench& bench)
addCoin(3 * COIN, wallet, wtxs);
// Create coins
- std::vector<COutput> coins;
+ wallet::CoinsResult available_coins;
for (const auto& wtx : wtxs) {
- coins.emplace_back(COutPoint(wtx->GetHash(), 0), wtx->tx->vout.at(0), /*depth=*/6 * 24, GetTxSpendSize(wallet, *wtx, 0), /*spendable=*/true, /*solvable=*/true, /*safe=*/true, wtx->GetTxTime(), /*from_me=*/true, /*fees=*/ 0);
+ const auto txout = wtx->tx->vout.at(0);
+ available_coins.coins[OutputType::BECH32].emplace_back(COutPoint(wtx->GetHash(), 0), txout, /*depth=*/6 * 24, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/true, /*solvable=*/true, /*safe=*/true, wtx->GetTxTime(), /*from_me=*/true, /*fees=*/ 0);
}
const CoinEligibilityFilter filter_standard(1, 6, 0);
@@ -75,7 +76,7 @@ static void CoinSelection(benchmark::Bench& bench)
/*avoid_partial=*/ false,
};
bench.run([&] {
- auto result = AttemptSelection(wallet, 1003 * COIN, filter_standard, coins, coin_selection_params);
+ auto result = AttemptSelection(wallet, 1003 * COIN, filter_standard, available_coins, coin_selection_params, /*allow_mixed_output_types=*/true);
assert(result);
assert(result->GetSelectedValue() == 1003 * COIN);
assert(result->GetInputSet().size() == 2);
diff --git a/src/bench/descriptors.cpp b/src/bench/descriptors.cpp
new file mode 100644
index 0000000000..5c868a8573
--- /dev/null
+++ b/src/bench/descriptors.cpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2019 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+#include <key.h>
+#include <script/descriptor.h>
+#include <script/standard.h>
+
+#include <string>
+#include <utility>
+
+static void ExpandDescriptor(benchmark::Bench& bench)
+{
+ const auto desc_str = "sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))";
+ const std::pair<int64_t, int64_t> range = {0, 1000};
+ FlatSigningProvider provider;
+ std::string error;
+ auto desc = Parse(desc_str, provider, error);
+
+ bench.run([&] {
+ for (int i = range.first; i <= range.second; ++i) {
+ std::vector<CScript> scripts;
+ bool success = desc->Expand(i, provider, scripts, provider);
+ assert(success);
+ }
+ });
+}
+
+BENCHMARK(ExpandDescriptor);
diff --git a/src/bench/gcs_filter.cpp b/src/bench/gcs_filter.cpp
index 607e4392b7..80babb213b 100644
--- a/src/bench/gcs_filter.cpp
+++ b/src/bench/gcs_filter.cpp
@@ -5,39 +5,84 @@
#include <bench/bench.h>
#include <blockfilter.h>
-static void ConstructGCSFilter(benchmark::Bench& bench)
+static const GCSFilter::ElementSet GenerateGCSTestElements()
{
GCSFilter::ElementSet elements;
- for (int i = 0; i < 10000; ++i) {
+
+ // Testing the benchmarks with different number of elements show that a filter
+ // with at least 100,000 elements results in benchmarks that have the same
+ // ns/op. This makes it easy to reason about how long (in nanoseconds) a single
+ // filter element takes to process.
+ for (int i = 0; i < 100000; ++i) {
GCSFilter::Element element(32);
element[0] = static_cast<unsigned char>(i);
element[1] = static_cast<unsigned char>(i >> 8);
elements.insert(std::move(element));
}
+ return elements;
+}
+
+static void GCSBlockFilterGetHash(benchmark::Bench& bench)
+{
+ auto elements = GenerateGCSTestElements();
+
+ GCSFilter filter({0, 0, BASIC_FILTER_P, BASIC_FILTER_M}, elements);
+ BlockFilter block_filter(BlockFilterType::BASIC, {}, filter.GetEncoded(), /*skip_decode_check=*/false);
+
+ bench.run([&] {
+ block_filter.GetHash();
+ });
+}
+
+static void GCSFilterConstruct(benchmark::Bench& bench)
+{
+ auto elements = GenerateGCSTestElements();
+
uint64_t siphash_k0 = 0;
- bench.batch(elements.size()).unit("elem").run([&] {
- GCSFilter filter({siphash_k0, 0, 20, 1 << 20}, elements);
+ bench.run([&]{
+ GCSFilter filter({siphash_k0, 0, BASIC_FILTER_P, BASIC_FILTER_M}, elements);
siphash_k0++;
});
}
-static void MatchGCSFilter(benchmark::Bench& bench)
+static void GCSFilterDecode(benchmark::Bench& bench)
{
- GCSFilter::ElementSet elements;
- for (int i = 0; i < 10000; ++i) {
- GCSFilter::Element element(32);
- element[0] = static_cast<unsigned char>(i);
- element[1] = static_cast<unsigned char>(i >> 8);
- elements.insert(std::move(element));
- }
- GCSFilter filter({0, 0, 20, 1 << 20}, elements);
+ auto elements = GenerateGCSTestElements();
- bench.unit("elem").run([&] {
- filter.Match(GCSFilter::Element());
+ GCSFilter filter({0, 0, BASIC_FILTER_P, BASIC_FILTER_M}, elements);
+ auto encoded = filter.GetEncoded();
+
+ bench.run([&] {
+ GCSFilter filter({0, 0, BASIC_FILTER_P, BASIC_FILTER_M}, encoded, /*skip_decode_check=*/false);
});
}
-BENCHMARK(ConstructGCSFilter);
-BENCHMARK(MatchGCSFilter);
+static void GCSFilterDecodeSkipCheck(benchmark::Bench& bench)
+{
+ auto elements = GenerateGCSTestElements();
+
+ GCSFilter filter({0, 0, BASIC_FILTER_P, BASIC_FILTER_M}, elements);
+ auto encoded = filter.GetEncoded();
+
+ bench.run([&] {
+ GCSFilter filter({0, 0, BASIC_FILTER_P, BASIC_FILTER_M}, encoded, /*skip_decode_check=*/true);
+ });
+}
+
+static void GCSFilterMatch(benchmark::Bench& bench)
+{
+ auto elements = GenerateGCSTestElements();
+
+ GCSFilter filter({0, 0, BASIC_FILTER_P, BASIC_FILTER_M}, elements);
+
+ bench.run([&] {
+ filter.Match(GCSFilter::Element());
+ });
+}
+BENCHMARK(GCSBlockFilterGetHash);
+BENCHMARK(GCSFilterConstruct);
+BENCHMARK(GCSFilterDecode);
+BENCHMARK(GCSFilterDecodeSkipCheck);
+BENCHMARK(GCSFilterMatch);
diff --git a/src/bench/wallet_loading.cpp b/src/bench/wallet_loading.cpp
index 38d3460001..27e4dd015d 100644
--- a/src/bench/wallet_loading.cpp
+++ b/src/bench/wallet_loading.cpp
@@ -17,20 +17,17 @@
#include <optional>
using wallet::CWallet;
+using wallet::DatabaseFormat;
using wallet::DatabaseOptions;
-using wallet::DatabaseStatus;
-using wallet::ISMINE_SPENDABLE;
-using wallet::MakeWalletDatabase;
+using wallet::TxStateInactive;
using wallet::WALLET_FLAG_DESCRIPTORS;
using wallet::WalletContext;
+using wallet::WalletDatabase;
-static const std::shared_ptr<CWallet> BenchLoadWallet(WalletContext& context, DatabaseOptions& options)
+static const std::shared_ptr<CWallet> BenchLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, DatabaseOptions& options)
{
- DatabaseStatus status;
bilingual_str error;
std::vector<bilingual_str> warnings;
- auto database = MakeWalletDatabase("", options, status, error);
- assert(database);
auto wallet = CWallet::Create(context, "", std::move(database), options.create_flags, error, warnings);
NotifyWalletLoaded(context, wallet);
if (context.chain) {
@@ -46,9 +43,43 @@ static void BenchUnloadWallet(std::shared_ptr<CWallet>&& wallet)
UnloadWallet(std::move(wallet));
}
+static void AddTx(CWallet& wallet)
+{
+ CMutableTransaction mtx;
+ mtx.vout.push_back({COIN, GetScriptForDestination(*Assert(wallet.GetNewDestination(OutputType::BECH32, "")))});
+ mtx.vin.push_back(CTxIn());
+
+ wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInactive{});
+}
+
+static std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database, DatabaseOptions& options)
+{
+ auto new_database = CreateMockWalletDatabase(options);
+
+ // Get a cursor to the original database
+ auto batch = database.MakeBatch();
+ batch->StartCursor();
+
+ // Get a batch for the new database
+ auto new_batch = new_database->MakeBatch();
+
+ // Read all records from the original database and write them to the new one
+ while (true) {
+ CDataStream key(SER_DISK, CLIENT_VERSION);
+ CDataStream value(SER_DISK, CLIENT_VERSION);
+ bool complete;
+ batch->ReadAtCursor(key, value, complete);
+ if (complete) break;
+ new_batch->Write(key, value);
+ }
+
+ return new_database;
+}
+
static void WalletLoading(benchmark::Bench& bench, bool legacy_wallet)
{
const auto test_setup = MakeNoLogFileContext<TestingSetup>();
+ test_setup->m_args.ForceSetArg("-unsafesqlitesync", "1");
WalletContext context;
context.args = &test_setup->m_args;
@@ -57,27 +88,40 @@ static void WalletLoading(benchmark::Bench& bench, bool legacy_wallet)
// Setup the wallet
// Loading the wallet will also create it
DatabaseOptions options;
- if (!legacy_wallet) options.create_flags = WALLET_FLAG_DESCRIPTORS;
- auto wallet = BenchLoadWallet(context, options);
+ if (legacy_wallet) {
+ options.require_format = DatabaseFormat::BERKELEY;
+ } else {
+ options.create_flags = WALLET_FLAG_DESCRIPTORS;
+ options.require_format = DatabaseFormat::SQLITE;
+ }
+ auto database = CreateMockWalletDatabase(options);
+ auto wallet = BenchLoadWallet(std::move(database), context, options);
// Generate a bunch of transactions and addresses to put into the wallet
- for (int i = 0; i < 5000; ++i) {
- generatetoaddress(test_setup->m_node, getnewaddress(*wallet));
+ for (int i = 0; i < 1000; ++i) {
+ AddTx(*wallet);
}
+ database = DuplicateMockDatabase(wallet->GetDatabase(), options);
+
// reload the wallet for the actual benchmark
BenchUnloadWallet(std::move(wallet));
- bench.minEpochIterations(10).run([&] {
- wallet = BenchLoadWallet(context, options);
+ bench.epochs(5).run([&] {
+ wallet = BenchLoadWallet(std::move(database), context, options);
// Cleanup
+ database = DuplicateMockDatabase(wallet->GetDatabase(), options);
BenchUnloadWallet(std::move(wallet));
});
}
+#ifdef USE_BDB
static void WalletLoadingLegacy(benchmark::Bench& bench) { WalletLoading(bench, /*legacy_wallet=*/true); }
-static void WalletLoadingDescriptors(benchmark::Bench& bench) { WalletLoading(bench, /*legacy_wallet=*/false); }
-
BENCHMARK(WalletLoadingLegacy);
+#endif
+
+#ifdef USE_SQLITE
+static void WalletLoadingDescriptors(benchmark::Bench& bench) { WalletLoading(bench, /*legacy_wallet=*/false); }
BENCHMARK(WalletLoadingDescriptors);
+#endif
diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp
index 1817aa1a53..d972b71a65 100644
--- a/src/bitcoin-chainstate.cpp
+++ b/src/bitcoin-chainstate.cpp
@@ -13,11 +13,13 @@
#include <kernel/checks.h>
#include <kernel/context.h>
+#include <kernel/validation_cache_sizes.h>
#include <chainparams.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <node/blockstorage.h>
+#include <node/caches.h>
#include <node/chainstate.h>
#include <scheduler.h>
#include <script/sigcache.h>
@@ -61,8 +63,9 @@ int main(int argc, char* argv[])
// Necessary for CheckInputScripts (eventually called by ProcessNewBlock),
// which will try the script cache first and fall back to actually
// performing the check with the signature cache.
- InitSignatureCache();
- InitScriptExecutionCache();
+ kernel::ValidationCacheSizes validation_cache_sizes{};
+ Assert(InitSignatureCache(validation_cache_sizes.signature_cache_bytes));
+ Assert(InitScriptExecutionCache(validation_cache_sizes.script_execution_cache_bytes));
// SETUP: Scheduling and Background Signals
@@ -78,38 +81,30 @@ int main(int argc, char* argv[])
// SETUP: Chainstate
const ChainstateManager::Options chainman_opts{
- chainparams,
- static_cast<int64_t(*)()>(GetTime),
+ .chainparams = chainparams,
+ .adjusted_time_callback = NodeClock::now,
};
ChainstateManager chainman{chainman_opts};
- auto rv = node::LoadChainstate(false,
- std::ref(chainman),
- nullptr,
- false,
- false,
- 2 << 20,
- 2 << 22,
- (450 << 20) - (2 << 20) - (2 << 22),
- false,
- false,
- []() { return false; });
- if (rv.has_value()) {
+ node::CacheSizes cache_sizes;
+ cache_sizes.block_tree_db = 2 << 20;
+ cache_sizes.coins_db = 2 << 22;
+ cache_sizes.coins = (450 << 20) - (2 << 20) - (2 << 22);
+ node::ChainstateLoadOptions options;
+ options.check_interrupt = [] { return false; };
+ auto [status, error] = node::LoadChainstate(chainman, cache_sizes, options);
+ if (status != node::ChainstateLoadStatus::SUCCESS) {
std::cerr << "Failed to load Chain state from your datadir." << std::endl;
goto epilogue;
} else {
- auto maybe_verify_error = node::VerifyLoadedChainstate(std::ref(chainman),
- false,
- false,
- DEFAULT_CHECKBLOCKS,
- DEFAULT_CHECKLEVEL);
- if (maybe_verify_error.has_value()) {
+ std::tie(status, error) = node::VerifyLoadedChainstate(chainman, options);
+ if (status != node::ChainstateLoadStatus::SUCCESS) {
std::cerr << "Failed to verify loaded Chain state from your datadir." << std::endl;
goto epilogue;
}
}
- for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
+ for (Chainstate* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
BlockValidationState state;
if (!chainstate->ActivateBestChain(state, nullptr)) {
std::cerr << "Failed to connect best block (" << state.ToString() << ")" << std::endl;
@@ -120,12 +115,14 @@ int main(int argc, char* argv[])
// Main program logic starts here
std::cout
<< "Hello! I'm going to print out some information about your datadir." << std::endl
- << "\t" << "Path: " << gArgs.GetDataDirNet() << std::endl
+ << "\t" << "Path: " << gArgs.GetDataDirNet() << std::endl;
+ {
+ LOCK(chainman.GetMutex());
+ std::cout
<< "\t" << "Reindexing: " << std::boolalpha << node::fReindex.load() << std::noboolalpha << std::endl
<< "\t" << "Snapshot Active: " << std::boolalpha << chainman.IsSnapshotActive() << std::noboolalpha << std::endl
<< "\t" << "Active Height: " << chainman.ActiveHeight() << std::endl
<< "\t" << "Active IBD: " << std::boolalpha << chainman.ActiveChainstate().IsInitialBlockDownload() << std::noboolalpha << std::endl;
- {
CBlockIndex* tip = chainman.ActiveTip();
if (tip) {
std::cout << "\t" << tip->ToString() << std::endl;
@@ -198,7 +195,7 @@ int main(int argc, char* argv[])
bool new_block;
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
RegisterSharedValidationInterface(sc);
- bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*new_block=*/&new_block);
+ bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
UnregisterSharedValidationInterface(sc);
if (!new_block && accepted) {
std::cerr << "duplicate" << std::endl;
@@ -213,6 +210,9 @@ int main(int argc, char* argv[])
case BlockValidationResult::BLOCK_RESULT_UNSET:
std::cerr << "initial value. Block has not yet been rejected" << std::endl;
break;
+ case BlockValidationResult::BLOCK_HEADER_LOW_WORK:
+ std::cerr << "the block header may be on a too-little-work chain" << std::endl;
+ break;
case BlockValidationResult::BLOCK_CONSENSUS:
std::cerr << "invalid by consensus rules (excluding any below reasons)" << std::endl;
break;
@@ -253,7 +253,7 @@ epilogue:
GetMainSignals().FlushBackgroundCallbacks();
{
LOCK(cs_main);
- for (CChainState* chainstate : chainman.GetAll()) {
+ for (Chainstate* chainstate : chainman.GetAll()) {
if (chainstate->CanFlushToDisk()) {
chainstate->ForceFlushStateToDisk();
chainstate->ResetCoinsViews();
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 0db2b75384..e64e2202ba 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -9,7 +9,7 @@
#include <chainparamsbase.h>
#include <clientversion.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <compat/stdin.h>
#include <policy/feerate.h>
#include <rpc/client.h>
@@ -807,7 +807,7 @@ static UniValue CallRPC(BaseRequestHandler* rh, const std::string& strMethod, co
if (failedToGetAuthCookie) {
throw std::runtime_error(strprintf(
"Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
- fs::PathToString(GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)))));
+ fs::PathToString(GetConfigFile(gArgs.GetPathArg("-conf", BITCOIN_CONF_FILENAME)))));
} else {
throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
}
@@ -911,7 +911,7 @@ static void GetWalletBalances(UniValue& result)
UniValue balances(UniValue::VOBJ);
for (const UniValue& wallet : wallets.getValues()) {
- const std::string wallet_name = wallet.get_str();
+ const std::string& wallet_name = wallet.get_str();
const UniValue getbalances = ConnectAndCallRPC(&rh, "getbalances", /* args=*/{}, wallet_name);
const UniValue& balance = find_value(getbalances, "result")["mine"]["trusted"];
balances.pushKV(wallet_name, balance);
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index e0d5c6e5dc..d49dc72abf 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -8,14 +8,13 @@
#include <clientversion.h>
#include <coins.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <consensus/amount.h>
#include <consensus/consensus.h>
#include <core_io.h>
#include <key_io.h>
#include <fs.h>
#include <policy/policy.h>
-#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <script/script.h>
#include <script/sign.h>
@@ -596,7 +595,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
UniValue prevtxsObj = registers["prevtxs"];
{
for (unsigned int previdx = 0; previdx < prevtxsObj.size(); previdx++) {
- UniValue prevOut = prevtxsObj[previdx];
+ const UniValue& prevOut = prevtxsObj[previdx];
if (!prevOut.isObject())
throw std::runtime_error("expected prevtxs internal object");
diff --git a/src/bitcoin-util.cpp b/src/bitcoin-util.cpp
index 1739804edb..fb184c0486 100644
--- a/src/bitcoin-util.cpp
+++ b/src/bitcoin-util.cpp
@@ -11,7 +11,7 @@
#include <chainparams.h>
#include <chainparamsbase.h>
#include <clientversion.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <core_io.h>
#include <streams.h>
#include <util/system.h>
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index 7bec3292a1..a7d49452b0 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -9,7 +9,7 @@
#include <chainparams.h>
#include <chainparamsbase.h>
#include <clientversion.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <interfaces/init.h>
#include <key.h>
#include <logging.h>
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index be894e192e..85ba88f6ab 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -9,7 +9,7 @@
#include <chainparams.h>
#include <clientversion.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <init.h>
#include <interfaces/chain.h>
#include <interfaces/init.h>
diff --git a/src/blockfilter.cpp b/src/blockfilter.cpp
index 63a9ba498f..85929747be 100644
--- a/src/blockfilter.cpp
+++ b/src/blockfilter.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <mutex>
-#include <sstream>
#include <set>
#include <blockfilter.h>
@@ -13,6 +12,7 @@
#include <script/script.h>
#include <streams.h>
#include <util/golombrice.h>
+#include <util/string.h>
/// SerType used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_TYPE = SER_NETWORK;
@@ -47,7 +47,7 @@ GCSFilter::GCSFilter(const Params& params)
: m_params(params), m_N(0), m_F(0), m_encoded{0}
{}
-GCSFilter::GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter)
+GCSFilter::GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter, bool skip_decode_check)
: m_params(params), m_encoded(std::move(encoded_filter))
{
SpanReader stream{GCS_SER_TYPE, GCS_SER_VERSION, m_encoded};
@@ -59,6 +59,8 @@ GCSFilter::GCSFilter(const Params& params, std::vector<unsigned char> encoded_fi
}
m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_params.m_M);
+ if (skip_decode_check) return;
+
// Verify that the encoded filter contains exactly N elements. If it has too much or too little
// data, a std::ios_base::failure exception will be raised.
BitStreamReader<SpanReader> bitreader{stream};
@@ -146,7 +148,7 @@ bool GCSFilter::MatchAny(const ElementSet& elements) const
const std::string& BlockFilterTypeName(BlockFilterType filter_type)
{
- static std::string unknown_retval = "";
+ static std::string unknown_retval;
auto it = g_filter_types.find(filter_type);
return it != g_filter_types.end() ? it->second : unknown_retval;
}
@@ -167,7 +169,7 @@ const std::set<BlockFilterType>& AllBlockFilterTypes()
static std::once_flag flag;
std::call_once(flag, []() {
- for (auto entry : g_filter_types) {
+ for (const auto& entry : g_filter_types) {
types.insert(entry.first);
}
});
@@ -177,19 +179,7 @@ const std::set<BlockFilterType>& AllBlockFilterTypes()
const std::string& ListBlockFilterTypes()
{
- static std::string type_list;
-
- static std::once_flag flag;
- std::call_once(flag, []() {
- std::stringstream ret;
- bool first = true;
- for (auto entry : g_filter_types) {
- if (!first) ret << ", ";
- ret << entry.second;
- first = false;
- }
- type_list = ret.str();
- });
+ static std::string type_list{Join(g_filter_types, ", ", [](const auto& entry) { return entry.second; })};
return type_list;
}
@@ -219,14 +209,14 @@ static GCSFilter::ElementSet BasicFilterElements(const CBlock& block,
}
BlockFilter::BlockFilter(BlockFilterType filter_type, const uint256& block_hash,
- std::vector<unsigned char> filter)
+ std::vector<unsigned char> filter, bool skip_decode_check)
: m_filter_type(filter_type), m_block_hash(block_hash)
{
GCSFilter::Params params;
if (!BuildParams(params)) {
throw std::invalid_argument("unknown filter_type");
}
- m_filter = GCSFilter(params, std::move(filter));
+ m_filter = GCSFilter(params, std::move(filter), skip_decode_check);
}
BlockFilter::BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo)
diff --git a/src/blockfilter.h b/src/blockfilter.h
index 96cefbf3b2..0cb627d9df 100644
--- a/src/blockfilter.h
+++ b/src/blockfilter.h
@@ -11,6 +11,7 @@
#include <unordered_set>
#include <vector>
+#include <attributes.h>
#include <primitives/block.h>
#include <serialize.h>
#include <uint256.h>
@@ -59,14 +60,14 @@ public:
explicit GCSFilter(const Params& params = Params());
/** Reconstructs an already-created filter from an encoding. */
- GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter);
+ GCSFilter(const Params& params, std::vector<unsigned char> encoded_filter, bool skip_decode_check);
/** Builds a new filter from the params and set of elements. */
GCSFilter(const Params& params, const ElementSet& elements);
uint32_t GetN() const { return m_N; }
- const Params& GetParams() const { return m_params; }
- const std::vector<unsigned char>& GetEncoded() const { return m_encoded; }
+ const Params& GetParams() const LIFETIMEBOUND { return m_params; }
+ const std::vector<unsigned char>& GetEncoded() const LIFETIMEBOUND { return m_encoded; }
/**
* Checks if the element may be in the set. False positives are possible
@@ -122,16 +123,16 @@ public:
//! Reconstruct a BlockFilter from parts.
BlockFilter(BlockFilterType filter_type, const uint256& block_hash,
- std::vector<unsigned char> filter);
+ std::vector<unsigned char> filter, bool skip_decode_check);
//! Construct a new BlockFilter of the specified type from a block.
BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo);
BlockFilterType GetFilterType() const { return m_filter_type; }
- const uint256& GetBlockHash() const { return m_block_hash; }
- const GCSFilter& GetFilter() const { return m_filter; }
+ const uint256& GetBlockHash() const LIFETIMEBOUND { return m_block_hash; }
+ const GCSFilter& GetFilter() const LIFETIMEBOUND { return m_filter; }
- const std::vector<unsigned char>& GetEncodedFilter() const
+ const std::vector<unsigned char>& GetEncodedFilter() const LIFETIMEBOUND
{
return m_filter.GetEncoded();
}
@@ -164,7 +165,7 @@ public:
if (!BuildParams(params)) {
throw std::ios_base::failure("unknown filter_type");
}
- m_filter = GCSFilter(params, std::move(encoded_filter));
+ m_filter = GCSFilter(params, std::move(encoded_filter), /*skip_decode_check=*/false);
}
};
diff --git a/src/chain.cpp b/src/chain.cpp
index b8158f7b0b..66a0830394 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -4,6 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chain.h>
+#include <tinyformat.h>
#include <util/time.h>
std::string CBlockFileInfo::ToString() const
@@ -11,11 +12,15 @@ std::string CBlockFileInfo::ToString() const
return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, FormatISO8601Date(nTimeFirst), FormatISO8601Date(nTimeLast));
}
-void CChain::SetTip(CBlockIndex *pindex) {
- if (pindex == nullptr) {
- vChain.clear();
- return;
- }
+std::string CBlockIndex::ToString() const
+{
+ return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
+ pprev, nHeight, hashMerkleRoot.ToString(), GetBlockHash().ToString());
+}
+
+void CChain::SetTip(CBlockIndex& block)
+{
+ CBlockIndex* pindex = &block;
vChain.resize(pindex->nHeight + 1);
while (pindex && vChain[pindex->nHeight] != pindex) {
vChain[pindex->nHeight] = pindex;
@@ -23,32 +28,33 @@ void CChain::SetTip(CBlockIndex *pindex) {
}
}
-CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
- int nStep = 1;
- std::vector<uint256> vHave;
- vHave.reserve(32);
-
- if (!pindex)
- pindex = Tip();
- while (pindex) {
- vHave.push_back(pindex->GetBlockHash());
- // Stop when we have added the genesis block.
- if (pindex->nHeight == 0)
- break;
+std::vector<uint256> LocatorEntries(const CBlockIndex* index)
+{
+ int step = 1;
+ std::vector<uint256> have;
+ if (index == nullptr) return have;
+
+ have.reserve(32);
+ while (index) {
+ have.emplace_back(index->GetBlockHash());
+ if (index->nHeight == 0) break;
// Exponentially larger steps back, plus the genesis block.
- int nHeight = std::max(pindex->nHeight - nStep, 0);
- if (Contains(pindex)) {
- // Use O(1) CChain index if possible.
- pindex = (*this)[nHeight];
- } else {
- // Otherwise, use O(log n) skiplist.
- pindex = pindex->GetAncestor(nHeight);
- }
- if (vHave.size() > 10)
- nStep *= 2;
+ int height = std::max(index->nHeight - step, 0);
+ // Use skiplist.
+ index = index->GetAncestor(height);
+ if (have.size() > 10) step *= 2;
}
+ return have;
+}
- return CBlockLocator(vHave);
+CBlockLocator GetLocator(const CBlockIndex* index)
+{
+ return CBlockLocator{LocatorEntries(index)};
+}
+
+CBlockLocator CChain::GetLocator() const
+{
+ return ::GetLocator(Tip());
}
const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
diff --git a/src/chain.h b/src/chain.h
index ecc2ae732f..2d3b084b9b 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -11,8 +11,8 @@
#include <flatfile.h>
#include <primitives/block.h>
#include <sync.h>
-#include <tinyformat.h>
#include <uint256.h>
+#include <util/time.h>
#include <vector>
@@ -263,6 +263,7 @@ public:
uint256 GetBlockHash() const
{
+ assert(phashBlock != nullptr);
return *phashBlock;
}
@@ -275,6 +276,11 @@ public:
*/
bool HaveTxsDownloaded() const { return nChainTx != 0; }
+ NodeSeconds Time() const
+ {
+ return NodeSeconds{std::chrono::seconds{nTime}};
+ }
+
int64_t GetBlockTime() const
{
return (int64_t)nTime;
@@ -301,13 +307,7 @@ public:
return pbegin[(pend - pbegin) / 2];
}
- std::string ToString() const
- {
- return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
- pprev, nHeight,
- hashMerkleRoot.ToString(),
- GetBlockHash().ToString());
- }
+ std::string ToString() const;
//! Check whether this block index entry is valid up to the passed validity level.
bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const
@@ -402,7 +402,7 @@ public:
READWRITE(obj.nNonce);
}
- uint256 GetBlockHash() const
+ uint256 ConstructBlockHash() const
{
CBlockHeader block;
block.nVersion = nVersion;
@@ -414,16 +414,8 @@ public:
return block.GetHash();
}
-
- std::string ToString() const
- {
- std::string str = "CDiskBlockIndex(";
- str += CBlockIndex::ToString();
- str += strprintf("\n hashBlock=%s, hashPrev=%s)",
- GetBlockHash().ToString(),
- hashPrev.ToString());
- return str;
- }
+ uint256 GetBlockHash() = delete;
+ std::string ToString() = delete;
};
/** An in-memory indexed chain of blocks. */
@@ -479,10 +471,10 @@ public:
}
/** Set/initialize a chain with a given tip. */
- void SetTip(CBlockIndex* pindex);
+ void SetTip(CBlockIndex& block);
- /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
- CBlockLocator GetLocator(const CBlockIndex* pindex = nullptr) const;
+ /** Return a CBlockLocator that refers to the tip in of this chain. */
+ CBlockLocator GetLocator() const;
/** Find the last common block between this chain and a block index entry. */
const CBlockIndex* FindFork(const CBlockIndex* pindex) const;
@@ -491,4 +483,10 @@ public:
CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
};
+/** Get a locator for a block index entry. */
+CBlockLocator GetLocator(const CBlockIndex* index);
+
+/** Construct a list of hash entries to put in a locator. */
+std::vector<uint256> LocatorEntries(const CBlockIndex* index);
+
#endif // BITCOIN_CHAIN_H
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 7a7c72ea25..c6d4eee7b9 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -93,8 +93,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("0x00000000000000000000000000000000000000002927cdceccbd5209e81e80db");
- consensus.defaultAssumeValid = uint256S("0x000000000000000000052d314a259755ca65944e68df6b12a067ea8f1f5a7091"); // 724466
+ consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000003404ba0801921119f903495e");
+ consensus.defaultAssumeValid = uint256S("0x00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd"); // 751565
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -107,7 +107,7 @@ public:
pchMessageStart[3] = 0xd9;
nDefaultPort = 8333;
nPruneAfterHeight = 100000;
- m_assumed_blockchain_size = 460;
+ m_assumed_blockchain_size = 496;
m_assumed_chain_state_size = 6;
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
@@ -168,10 +168,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 000000000000000000052d314a259755ca65944e68df6b12a067ea8f1f5a7091
- /* nTime */ 1645542140,
- /* nTxCount */ 712531200,
- /* dTxRate */ 2.891036496010309,
+ // Data from RPC: getchaintxstats 4096 00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd
+ .nTime = 1661697692,
+ .nTxCount = 760120522,
+ .dTxRate = 2.925802860942233,
};
}
};
@@ -213,8 +213,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("0x00000000000000000000000000000000000000000000064728c7be6fe4b2f961");
- consensus.defaultAssumeValid = uint256S("0x00000000000163cfb1f97c4e4098a3692c8053ad9cab5ad9c86b338b5c00b8b7"); // 2143398
+ consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000076f6e7cbd0beade5d20");
+ consensus.defaultAssumeValid = uint256S("0x0000000000000004877fa2d36316398528de4f347df2f8a96f76613a298ce060"); // 2344474
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
@@ -222,7 +222,7 @@ public:
pchMessageStart[3] = 0x07;
nDefaultPort = 18333;
nPruneAfterHeight = 1000;
- m_assumed_blockchain_size = 40;
+ m_assumed_blockchain_size = 42;
m_assumed_chain_state_size = 2;
genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN);
@@ -264,10 +264,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 00000000d18cfe81cbeea665076807789bd8f831d557632e635bc6e3c003069e
- /* nTime */ 1645635119,
- /* nTxCount */ 62226341,
- /* dTxRate */ 0.07717997442177152,
+ // Data from RPC: getchaintxstats 4096 0000000000000004877fa2d36316398528de4f347df2f8a96f76613a298ce060
+ .nTime = 1661705221,
+ .nTxCount = 63531852,
+ .dTxRate = 0.1079119341520164,
};
}
};
@@ -289,15 +289,15 @@ public:
vSeeds.emplace_back("178.128.221.177");
vSeeds.emplace_back("v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333");
- consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000000de26b0e471");
- consensus.defaultAssumeValid = uint256S("0x00000112852484b5fe3451572368f93cfd2723279af3464e478aee35115256ef"); // 78788
+ consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000001291fc22898");
+ consensus.defaultAssumeValid = uint256S("0x000000d1a0e224fa4679d2fb2187ba55431c284fa1b74cbc8cfda866fd4d2c09"); // 105495
m_assumed_blockchain_size = 1;
m_assumed_chain_state_size = 0;
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 0000003d9144c56ac110ae04a0c271a0acce2f14f426b39fdf0d938c96d2eb09
- /* nTime */ 1645631279,
- /* nTxCount */ 1257429,
- /* dTxRate */ 0.1389638742514995,
+ // Data from RPC: getchaintxstats 4096 000000d1a0e224fa4679d2fb2187ba55431c284fa1b74cbc8cfda866fd4d2c09
+ .nTime = 1661702566,
+ .nTxCount = 1903567,
+ .dTxRate = 0.02336701143027275,
};
} else {
const auto signet_challenge = args.GetArgs("-signetchallenge");
@@ -352,7 +352,7 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay
// message start is defined as the first 4 bytes of the sha256d of the block script
- CHashWriter h(SER_DISK, 0);
+ HashWriter h{};
h << consensus.signet_challenge;
uint256 hash = h.GetHash();
memcpy(pchMessageStart, hash.begin(), 4);
diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h
index b9df1c61f0..f065647d49 100644
--- a/src/chainparamsseeds.h
+++ b/src/chainparamsseeds.h
@@ -7,703 +7,945 @@
* Each line contains a BIP155 serialized (networkID, addr, port) tuple.
*/
static const uint8_t chainparams_seed_main[] = {
- 0x01,0x04,0x02,0x25,0x1e,0x90,0x22,0x49,
- 0x01,0x04,0x02,0x8a,0xae,0x9e,0x20,0x8d,
+ 0x01,0x04,0x02,0x03,0x19,0xb5,0x20,0x8d,
0x01,0x04,0x02,0x98,0x4e,0x7c,0x20,0x8d,
- 0x01,0x04,0x05,0x08,0x12,0x9a,0x20,0x8d,
- 0x01,0x04,0x05,0x2d,0x4a,0x32,0x20,0x8d,
- 0x01,0x04,0x05,0x4f,0x7b,0x03,0x20,0x8d,
- 0x01,0x04,0x05,0x66,0xa8,0xd9,0x56,0xcc,
- 0x01,0x04,0x05,0x67,0x89,0x92,0x24,0x75,
+ 0x01,0x04,0x05,0x27,0x4a,0xa6,0x20,0x8d,
+ 0x01,0x04,0x05,0x2d,0x4f,0x51,0x47,0x9c,
+ 0x01,0x04,0x05,0x35,0x10,0x80,0x20,0x8d,
+ 0x01,0x04,0x05,0x5f,0xba,0x4e,0x20,0x8d,
0x01,0x04,0x05,0x80,0x57,0x7e,0x20,0x8d,
- 0x01,0x04,0x05,0xac,0x84,0xc8,0x20,0x8d,
+ 0x01,0x04,0x05,0x85,0x41,0x52,0x20,0x8d,
+ 0x01,0x04,0x05,0x92,0x14,0xe5,0x20,0x8d,
+ 0x01,0x04,0x05,0xb4,0x29,0x77,0x20,0x8d,
0x01,0x04,0x05,0xbc,0x3e,0x12,0x20,0x8d,
- 0x01,0x04,0x05,0xfe,0x65,0xe2,0x20,0x8e,
- 0x01,0x04,0x08,0xd2,0x12,0x38,0x20,0x8d,
- 0x01,0x04,0x08,0xd2,0x5c,0x20,0x20,0x8d,
- 0x01,0x04,0x0e,0x0d,0x22,0xe1,0x3f,0x35,
- 0x01,0x04,0x0e,0x27,0x97,0xa7,0x20,0x8d,
- 0x01,0x04,0x12,0xc4,0x4f,0x6c,0x20,0x8d,
- 0x01,0x04,0x12,0xda,0x8b,0x3a,0xbc,0xcd,
- 0x01,0x04,0x14,0xb8,0x0f,0x74,0x20,0xf1,
- 0x01,0x04,0x17,0xaf,0x00,0xdc,0x20,0x8d,
+ 0x01,0x04,0x05,0xc7,0xad,0x42,0x20,0x8d,
+ 0x01,0x04,0x05,0xff,0x61,0x19,0x20,0x8d,
+ 0x01,0x04,0x05,0xff,0x67,0xb4,0x20,0x8d,
+ 0x01,0x04,0x08,0xd1,0x46,0x4d,0x20,0x8d,
+ 0x01,0x04,0x08,0xd1,0x69,0x8a,0x20,0x8d,
+ 0x01,0x04,0x12,0xa2,0xd0,0x99,0xbc,0xcc,
+ 0x01,0x04,0x17,0xaf,0x00,0xc8,0x20,0x8d,
+ 0x01,0x04,0x17,0xaf,0x00,0xde,0x20,0x8d,
0x01,0x04,0x17,0xe9,0x6b,0x15,0x20,0x8d,
+ 0x01,0x04,0x17,0xec,0x19,0xa9,0x20,0x8d,
0x01,0x04,0x18,0x23,0x44,0xe5,0x20,0x8d,
- 0x01,0x04,0x18,0x25,0x03,0x1a,0x20,0x8d,
- 0x01,0x04,0x18,0x66,0x5b,0xcb,0x20,0x8d,
+ 0x01,0x04,0x18,0x54,0xa4,0x32,0x20,0x8d,
0x01,0x04,0x18,0x74,0x99,0x73,0x20,0x8d,
- 0x01,0x04,0x18,0x86,0x06,0xa5,0x20,0x8d,
- 0x01,0x04,0x18,0x9b,0xda,0x0d,0x20,0x8d,
- 0x01,0x04,0x18,0xa0,0x89,0xad,0x20,0x8d,
- 0x01,0x04,0x18,0xb1,0x6a,0x55,0x20,0x8d,
0x01,0x04,0x18,0xb8,0x00,0x92,0x20,0x8d,
- 0x01,0x04,0x18,0xc2,0xde,0x74,0x20,0x8d,
- 0x01,0x04,0x18,0xcd,0xd7,0xc0,0x20,0x8d,
+ 0x01,0x04,0x1b,0x21,0xa0,0xc4,0x20,0x8d,
0x01,0x04,0x1b,0x7c,0x6c,0x13,0x20,0x8d,
- 0x01,0x04,0x1f,0x0e,0x28,0x40,0x20,0x8d,
+ 0x01,0x04,0x1b,0x94,0xce,0x8c,0x20,0x8d,
+ 0x01,0x04,0x1f,0x11,0x40,0xc0,0x20,0x8d,
+ 0x01,0x04,0x1f,0x12,0x72,0x87,0x20,0x8d,
+ 0x01,0x04,0x1f,0x29,0x17,0xf9,0x20,0x8d,
+ 0x01,0x04,0x1f,0x2a,0xb0,0x8a,0x20,0x8d,
0x01,0x04,0x1f,0x2f,0xca,0x70,0x20,0x8d,
- 0x01,0x04,0x1f,0xa5,0x73,0x07,0x20,0x8d,
0x01,0x04,0x22,0x41,0x2d,0x9d,0x20,0x8d,
- 0x01,0x04,0x22,0x4e,0x30,0x68,0x20,0x8d,
0x01,0x04,0x22,0x50,0x86,0x44,0x20,0x8d,
- 0x01,0x04,0x22,0x65,0x84,0xc6,0x20,0x8d,
- 0x01,0x04,0x22,0xe3,0x44,0xd8,0x20,0x8d,
- 0x01,0x04,0x23,0x89,0xd4,0x16,0x20,0x8d,
- 0x01,0x04,0x23,0xe7,0xbe,0x86,0x20,0x8d,
- 0x01,0x04,0x25,0x01,0xd9,0x23,0x20,0x8d,
- 0x01,0x04,0x25,0x0f,0x3e,0x20,0x20,0x8d,
+ 0x01,0x04,0x22,0x7e,0x73,0x23,0x20,0x8d,
+ 0x01,0x04,0x25,0x01,0xcc,0xe7,0x20,0x8d,
+ 0x01,0x04,0x25,0x78,0x9b,0x22,0x20,0x8d,
0x01,0x04,0x25,0x8f,0x76,0xae,0x20,0x8d,
- 0x01,0x04,0x25,0xc8,0x3b,0x43,0x20,0x8d,
- 0x01,0x04,0x25,0xcd,0x09,0xa5,0x20,0x8d,
- 0x01,0x04,0x26,0x17,0xb4,0xe4,0x20,0x8d,
- 0x01,0x04,0x26,0x41,0x77,0x1a,0x20,0x8d,
+ 0x01,0x04,0x25,0xc1,0xe3,0x10,0x20,0x8d,
+ 0x01,0x04,0x25,0xdc,0x87,0x97,0x20,0x8d,
+ 0x01,0x04,0x25,0xeb,0x92,0xec,0x20,0x8d,
+ 0x01,0x04,0x26,0x7c,0x7e,0x2a,0x20,0x8d,
0x01,0x04,0x26,0x8d,0x86,0x8c,0x20,0x8d,
- 0x01,0x04,0x27,0x6d,0x7a,0x7f,0x20,0xfc,
+ 0x01,0x04,0x26,0x91,0x97,0x96,0x20,0x8d,
+ 0x01,0x04,0x28,0x73,0x89,0x1c,0x20,0x8d,
+ 0x01,0x04,0x29,0x48,0x9a,0x42,0x20,0x8d,
0x01,0x04,0x29,0x4f,0x46,0x92,0x20,0x8d,
- 0x01,0x04,0x29,0xc1,0x7a,0xbf,0x20,0x8d,
+ 0x01,0x04,0x2a,0xc1,0x37,0x87,0x20,0x8d,
0x01,0x04,0x2b,0xe1,0x3e,0x6b,0x20,0x8d,
- 0x01,0x04,0x2d,0x23,0x49,0x98,0x20,0x8d,
0x01,0x04,0x2d,0x2b,0x61,0x67,0x20,0x8d,
- 0x01,0x04,0x2d,0x3f,0x0a,0x34,0x4e,0x28,
- 0x01,0x04,0x2d,0x54,0x99,0x28,0x20,0x8d,
- 0x01,0x04,0x2d,0x5f,0x40,0xe1,0x20,0x8d,
- 0x01,0x04,0x2d,0x81,0xb4,0xd6,0x20,0x8d,
- 0x01,0x04,0x2d,0x9a,0xff,0xa2,0x20,0x8d,
- 0x01,0x04,0x2d,0xe2,0x50,0x66,0x20,0x8d,
- 0x01,0x04,0x2e,0x06,0x0a,0xe6,0x20,0x8d,
+ 0x01,0x04,0x2d,0x55,0x30,0x3a,0x20,0x8d,
+ 0x01,0x04,0x2d,0x7e,0x1a,0xe5,0x20,0x8d,
+ 0x01,0x04,0x2d,0x86,0x8e,0x28,0x20,0x8d,
+ 0x01,0x04,0x2d,0x9a,0xfc,0xa2,0x20,0x8d,
+ 0x01,0x04,0x2e,0x0d,0xd8,0xa9,0x20,0x8d,
0x01,0x04,0x2e,0x17,0x57,0xda,0x20,0x8d,
- 0x01,0x04,0x2e,0x20,0x32,0x62,0x20,0x8d,
- 0x01,0x04,0x2e,0x2f,0x54,0x55,0x20,0x8d,
+ 0x01,0x04,0x2e,0x28,0x7f,0xa4,0x20,0x8d,
0x01,0x04,0x2e,0x30,0x7e,0x3a,0x20,0x8d,
+ 0x01,0x04,0x2e,0x3b,0x0d,0x23,0x20,0x8d,
+ 0x01,0x04,0x2e,0x48,0xee,0x11,0x20,0x8d,
+ 0x01,0x04,0x2e,0x80,0x8d,0xb8,0x20,0x8d,
0x01,0x04,0x2e,0x92,0xf8,0x59,0x20,0x8d,
0x01,0x04,0x2e,0xa5,0xdd,0xd1,0x24,0x75,
0x01,0x04,0x2e,0xa6,0x8e,0x02,0x20,0x8d,
- 0x01,0x04,0x2e,0xa6,0xa2,0x2d,0x4e,0x21,
- 0x01,0x04,0x2e,0xad,0x32,0x3a,0x20,0x8d,
0x01,0x04,0x2e,0xaf,0xb2,0x03,0x20,0x8d,
- 0x01,0x04,0x2e,0xbc,0x1e,0x76,0x20,0x8d,
- 0x01,0x04,0x2e,0xdb,0x78,0x3b,0x0e,0x59,
- 0x01,0x04,0x2e,0xe5,0xee,0xbb,0x20,0x8d,
- 0x01,0x04,0x2f,0x5d,0xe6,0xab,0x20,0x8d,
- 0x01,0x04,0x2f,0x64,0xa2,0xd2,0x47,0x9c,
- 0x01,0x04,0x2f,0x90,0x6a,0xf9,0x20,0x8d,
- 0x01,0x04,0x2f,0xbc,0x46,0xcd,0x20,0x8d,
- 0x01,0x04,0x2f,0xe3,0xe2,0xf2,0x20,0x8d,
+ 0x01,0x04,0x2f,0x24,0x90,0x33,0x20,0x8d,
+ 0x01,0x04,0x2f,0xb4,0x31,0x9e,0x20,0x8d,
+ 0x01,0x04,0x31,0xe4,0x83,0x85,0x08,0xa2,
0x01,0x04,0x32,0x02,0x0d,0xa4,0x20,0x8d,
- 0x01,0x04,0x32,0x05,0x2e,0xc3,0x20,0x8d,
- 0x01,0x04,0x32,0x2d,0x80,0x1c,0x20,0x8d,
- 0x01,0x04,0x33,0x94,0x99,0x3c,0x20,0x8d,
+ 0x01,0x04,0x32,0x23,0x47,0x33,0x20,0x8d,
+ 0x01,0x04,0x32,0x35,0xfa,0xa2,0x20,0x8d,
+ 0x01,0x04,0x33,0x44,0x24,0x39,0x20,0x8d,
+ 0x01,0x04,0x33,0x8a,0x04,0x87,0x75,0x31,
0x01,0x04,0x33,0x9a,0x3e,0x67,0x20,0x8d,
- 0x01,0x04,0x33,0x9a,0x83,0x12,0x20,0x8d,
0x01,0x04,0x33,0x9e,0x96,0x9b,0x20,0x8d,
- 0x01,0x04,0x33,0x9f,0x02,0xda,0x20,0x8d,
- 0x01,0x04,0x36,0xc6,0x13,0x22,0x20,0x8d,
- 0x01,0x04,0x3a,0x69,0xa8,0x29,0x20,0x8d,
+ 0x01,0x04,0x36,0xb0,0x3f,0x10,0x20,0x8d,
0x01,0x04,0x3a,0x9e,0x00,0x56,0x20,0x8d,
- 0x01,0x04,0x3c,0xfb,0x81,0x3d,0x20,0x90,
+ 0x01,0x04,0x3b,0x8a,0x73,0x89,0x20,0x8d,
+ 0x01,0x04,0x3b,0xa7,0xbf,0x3c,0x20,0x8d,
+ 0x01,0x04,0x3c,0xcd,0xcd,0x77,0x20,0x8d,
+ 0x01,0x04,0x3c,0xea,0x7a,0xf5,0x20,0x8d,
+ 0x01,0x04,0x3c,0xf0,0xd2,0x9b,0x20,0x8d,
0x01,0x04,0x3d,0xef,0x5b,0xfa,0x20,0x8d,
- 0x01,0x04,0x3e,0x1c,0xbe,0xc2,0x20,0x8d,
- 0x01,0x04,0x3e,0x98,0x3a,0x10,0x24,0xcd,
+ 0x01,0x04,0x3e,0x4a,0x8f,0x0b,0x20,0x8d,
+ 0x01,0x04,0x3e,0x8a,0xa2,0x0c,0x20,0x8d,
+ 0x01,0x04,0x3e,0xa9,0x4a,0xe9,0x20,0x8d,
0x01,0x04,0x3e,0xab,0x81,0x20,0x20,0x8d,
- 0x01,0x04,0x3e,0xfb,0x36,0xa3,0x20,0x8d,
+ 0x01,0x04,0x3e,0xd1,0xc6,0x41,0x20,0x8d,
0x01,0x04,0x3f,0xf7,0x93,0xa6,0x20,0x8d,
- 0x01,0x04,0x40,0x21,0x44,0xb0,0x20,0x8d,
- 0x01,0x04,0x40,0x9c,0xc0,0x3d,0x20,0x8d,
- 0x01,0x04,0x40,0xbb,0xaf,0xe2,0x20,0x8d,
- 0x01,0x04,0x40,0xe9,0xf5,0x27,0x20,0x8d,
- 0x01,0x04,0x40,0xed,0x52,0x95,0x20,0x8d,
- 0x01,0x04,0x41,0x65,0xf7,0x1a,0x20,0x8d,
+ 0x01,0x04,0x40,0x62,0x4c,0x3e,0x20,0x8d,
0x01,0x04,0x42,0x1d,0x81,0xda,0x20,0x8d,
- 0x01,0x04,0x42,0x31,0xcc,0x0b,0x20,0x8d,
- 0x01,0x04,0x42,0x3a,0xf3,0xd7,0x20,0x8d,
- 0x01,0x04,0x42,0x55,0xea,0x81,0x20,0x8d,
+ 0x01,0x04,0x42,0x60,0xeb,0x1c,0x20,0x8d,
0x01,0x04,0x42,0x82,0x78,0x34,0x20,0x8d,
- 0x01,0x04,0x43,0x0a,0x79,0x91,0x20,0x8d,
- 0x01,0x04,0x43,0xd2,0xe4,0xcb,0x20,0x8d,
- 0x01,0x04,0x43,0xd5,0x57,0x15,0x20,0x8d,
+ 0x01,0x04,0x42,0xc6,0xd1,0xf3,0x20,0x8d,
+ 0x01,0x04,0x42,0xd0,0x40,0x80,0x20,0x8d,
+ 0x01,0x04,0x42,0xe1,0xe7,0x94,0x20,0x8d,
+ 0x01,0x04,0x43,0x37,0x03,0xc8,0x20,0x8d,
+ 0x01,0x04,0x43,0x3a,0xe8,0x6b,0x20,0x8d,
+ 0x01,0x04,0x43,0xd3,0x5c,0x02,0x20,0x8d,
+ 0x01,0x04,0x43,0xdf,0x77,0x7a,0x20,0x8d,
+ 0x01,0x04,0x44,0x30,0x83,0xfb,0x20,0x8d,
0x01,0x04,0x44,0xb5,0x04,0x0c,0x20,0x8d,
- 0x01,0x04,0x45,0x07,0x7c,0x92,0x20,0x8d,
- 0x01,0x04,0x45,0x08,0xaf,0xc9,0x20,0x8d,
+ 0x01,0x04,0x45,0x0e,0xb9,0x09,0x20,0x8d,
+ 0x01,0x04,0x45,0x36,0x1d,0xc1,0x20,0x8d,
0x01,0x04,0x45,0x3b,0x12,0x16,0x20,0x8d,
- 0x01,0x04,0x45,0x77,0xc1,0x09,0x20,0x8d,
- 0x01,0x04,0x45,0x82,0xc9,0x1b,0x20,0x8d,
0x01,0x04,0x45,0x83,0x65,0xb0,0x20,0x8d,
- 0x01,0x04,0x46,0x0f,0xc2,0x20,0x20,0x8d,
- 0x01,0x04,0x46,0x40,0x1b,0x0c,0x20,0x8d,
- 0x01,0x04,0x48,0x1d,0xaa,0x97,0x20,0x8d,
- 0x01,0x04,0x48,0x4a,0x22,0x63,0x20,0x8d,
- 0x01,0x04,0x48,0x85,0xb1,0x77,0x20,0x8d,
- 0x01,0x04,0x49,0xa6,0x54,0xde,0x20,0x8d,
- 0x01,0x04,0x4a,0x43,0xf0,0xcc,0x20,0x8d,
+ 0x01,0x04,0x45,0xa5,0xcd,0x8e,0x22,0x81,
+ 0x01,0x04,0x45,0xe4,0xdb,0x7c,0x20,0x8d,
+ 0x01,0x04,0x46,0x3b,0x7b,0x19,0x20,0x8d,
+ 0x01,0x04,0x46,0x3e,0x0d,0x96,0x20,0x8d,
+ 0x01,0x04,0x46,0x42,0xf8,0xaa,0x20,0x8d,
+ 0x01,0x04,0x46,0x70,0x99,0xe5,0x20,0x8d,
+ 0x01,0x04,0x46,0xa0,0xf0,0x84,0x20,0x8d,
+ 0x01,0x04,0x46,0xbe,0xb1,0xcc,0x20,0x8d,
+ 0x01,0x04,0x47,0x1c,0xbd,0xef,0x20,0x8d,
+ 0x01,0x04,0x47,0xea,0x7d,0xc6,0x20,0x8d,
+ 0x01,0x04,0x48,0x4a,0x7b,0xb3,0x20,0x8d,
+ 0x01,0x04,0x48,0xfd,0xec,0xd9,0x20,0x8d,
+ 0x01,0x04,0x49,0xdb,0xfe,0x78,0x20,0x8d,
0x01,0x04,0x4a,0x5b,0x73,0xe5,0x20,0x8d,
0x01,0x04,0x4a,0x76,0x89,0x77,0x20,0x8d,
- 0x01,0x04,0x4a,0xd5,0xfb,0xcb,0x20,0x8d,
+ 0x01,0x04,0x4a,0xc3,0xa6,0x64,0x20,0x8d,
0x01,0x04,0x4a,0xdc,0xff,0xbe,0x20,0x8d,
- 0x01,0x04,0x4c,0x0b,0x3c,0x9b,0x20,0x8d,
- 0x01,0x04,0x4c,0x42,0x90,0x7f,0x20,0x8d,
+ 0x01,0x04,0x4c,0x43,0xd3,0x6e,0x20,0x8d,
+ 0x01,0x04,0x4c,0xa9,0xa3,0x0e,0x20,0x8d,
+ 0x01,0x04,0x4d,0x20,0x79,0xa2,0x20,0x8d,
+ 0x01,0x04,0x4d,0x35,0x87,0x4a,0x20,0x8d,
0x01,0x04,0x4d,0x46,0x10,0xf5,0x20,0x8d,
0x01,0x04,0x4d,0x55,0xcc,0x95,0x20,0x8d,
- 0x01,0x04,0x4d,0x69,0x57,0x61,0x20,0x8d,
- 0x01,0x04,0x4d,0x78,0x71,0x45,0x20,0xf1,
- 0x01,0x04,0x4d,0x78,0x71,0x47,0x20,0xf1,
- 0x01,0x04,0x4d,0x78,0x7a,0x74,0x20,0xf1,
- 0x01,0x04,0x4d,0x78,0x7a,0x76,0x20,0xf1,
+ 0x01,0x04,0x4d,0x6b,0x26,0xef,0x20,0x8d,
+ 0x01,0x04,0x4d,0x78,0x1a,0x66,0x20,0x8d,
0x01,0x04,0x4d,0xa2,0xbe,0x5a,0x20,0x8d,
- 0x01,0x04,0x4d,0xa7,0xf5,0xef,0xd8,0xf8,
- 0x01,0x04,0x4d,0xe8,0x29,0xbd,0x20,0x8d,
0x01,0x04,0x4e,0x14,0xe3,0xf9,0x20,0x8d,
0x01,0x04,0x4e,0x15,0xa7,0x08,0x20,0x8d,
0x01,0x04,0x4e,0x1b,0x8b,0x0d,0x20,0x8d,
- 0x01,0x04,0x4e,0x2b,0xd0,0x19,0x20,0x8d,
- 0x01,0x04,0x4e,0x3f,0x1c,0x92,0x20,0x8d,
- 0x01,0x04,0x4e,0x48,0xe4,0xef,0x20,0x8d,
- 0x01,0x04,0x4e,0x6c,0x66,0x08,0x20,0x8d,
- 0x01,0x04,0x4e,0x81,0x00,0x27,0x20,0x8d,
- 0x01,0x04,0x4e,0x81,0xa9,0x45,0x20,0x8d,
- 0x01,0x04,0x4f,0x4d,0xb6,0xb4,0x20,0x8d,
+ 0x01,0x04,0x4e,0x5a,0x5b,0xdc,0x20,0x8d,
+ 0x01,0x04,0x4e,0x6c,0x6c,0x19,0x20,0x8d,
+ 0x01,0x04,0x4e,0x6c,0x6c,0x26,0x20,0x8d,
0x01,0x04,0x4f,0x4d,0xb6,0xb7,0x20,0x8d,
- 0x01,0x04,0x4f,0x6b,0xb2,0x3b,0x20,0x8d,
+ 0x01,0x04,0x4f,0x62,0x9f,0x07,0x2c,0x45,
+ 0x01,0x04,0x4f,0xbd,0xd3,0xc9,0x20,0x8d,
0x01,0x04,0x50,0x37,0xe1,0x9e,0x20,0x8d,
- 0x01,0x04,0x50,0x40,0xd3,0x66,0x20,0x8d,
- 0x01,0x04,0x50,0x40,0xd3,0x67,0x20,0x8d,
- 0x01,0x04,0x50,0x47,0x39,0x32,0x20,0x8d,
- 0x01,0x04,0x50,0x51,0x03,0x1b,0x20,0x8d,
- 0x01,0x04,0x50,0x52,0x37,0x2b,0x20,0x8d,
+ 0x01,0x04,0x50,0x53,0xba,0x23,0x20,0x8d,
0x01,0x04,0x50,0x58,0xac,0xe3,0xfb,0x08,
- 0x01,0x04,0x50,0x59,0xcb,0xac,0x1f,0x41,
- 0x01,0x04,0x50,0x5d,0xd5,0xf6,0x20,0x8d,
- 0x01,0x04,0x50,0x93,0x52,0xa5,0x20,0x8d,
+ 0x01,0x04,0x50,0xd1,0x57,0x67,0x24,0x75,
0x01,0x04,0x50,0xe5,0x1c,0x3c,0x20,0x8d,
- 0x01,0x04,0x50,0xf7,0xe9,0x28,0x20,0x8d,
- 0x01,0x04,0x50,0xff,0x08,0x5d,0x20,0x8d,
+ 0x01,0x04,0x51,0x07,0x10,0xb6,0x20,0x8d,
0x01,0x04,0x51,0x07,0x11,0xca,0x20,0x8d,
- 0x01,0x04,0x51,0x0a,0xf1,0xa5,0x20,0x8d,
- 0x01,0x04,0x51,0x15,0x56,0x9d,0x20,0x8d,
+ 0x01,0x04,0x51,0x13,0x0a,0x02,0x20,0x8d,
+ 0x01,0x04,0x51,0x58,0xdd,0xbe,0x20,0x8d,
0x01,0x04,0x51,0xab,0x16,0x8f,0x20,0x8d,
- 0x01,0x04,0x51,0xed,0xce,0xe0,0x20,0x97,
- 0x01,0x04,0x52,0x45,0x17,0xc3,0x20,0x8d,
+ 0x01,0x04,0x51,0xe0,0x2c,0xa4,0x20,0x8d,
+ 0x01,0x04,0x51,0xe0,0xa0,0x51,0x20,0x8d,
+ 0x01,0x04,0x52,0x01,0x44,0x36,0x20,0x8d,
+ 0x01,0x04,0x52,0x15,0xa4,0x2f,0x20,0x8d,
+ 0x01,0x04,0x52,0x40,0x74,0x05,0x20,0x8d,
+ 0x01,0x04,0x52,0x42,0x0a,0x0b,0x20,0x8d,
0x01,0x04,0x52,0x60,0x60,0x28,0x20,0x8d,
0x01,0x04,0x52,0x74,0x32,0x65,0x20,0x8d,
+ 0x01,0x04,0x52,0x81,0x44,0x3e,0x20,0x8d,
0x01,0x04,0x52,0x88,0x63,0x7a,0x20,0x8d,
- 0x01,0x04,0x52,0x95,0x61,0x19,0x44,0x9f,
0x01,0x04,0x52,0x9a,0x18,0xd1,0x20,0x8d,
- 0x01,0x04,0x52,0xa5,0xf1,0x32,0x20,0x8d,
- 0x01,0x04,0x52,0xc5,0xda,0xfd,0x20,0x8d,
- 0x01,0x04,0x52,0xca,0x44,0xe7,0x20,0x8d,
+ 0x01,0x04,0x52,0xc5,0xd7,0x7d,0x20,0x8d,
+ 0x01,0x04,0x53,0x80,0x84,0x5b,0x20,0x8d,
0x01,0x04,0x53,0x89,0x29,0x0a,0x20,0x8d,
0x01,0x04,0x53,0xd0,0x06,0xd3,0x20,0x8d,
- 0x01,0x04,0x53,0xd9,0x08,0x1f,0xad,0x84,
- 0x01,0x04,0x53,0xdc,0x6e,0x30,0x20,0x8d,
+ 0x01,0x04,0x53,0xd0,0xc1,0xf2,0x20,0x8d,
0x01,0x04,0x53,0xde,0x8a,0x55,0x20,0x8d,
+ 0x01,0x04,0x53,0xf0,0x7c,0x44,0x20,0x8d,
0x01,0x04,0x53,0xf3,0xbf,0xc7,0x20,0x8d,
- 0x01,0x04,0x54,0x16,0x8b,0x39,0x20,0x8d,
- 0x01,0x04,0x54,0x1b,0x9b,0x11,0x20,0x8d,
- 0x01,0x04,0x54,0x4b,0x1c,0xf7,0x20,0x8d,
+ 0x01,0x04,0x54,0x09,0x05,0xd3,0x20,0x8d,
+ 0x01,0x04,0x54,0x1c,0x39,0x5a,0x20,0x8d,
+ 0x01,0x04,0x54,0x26,0x03,0xf9,0x20,0x8d,
0x01,0x04,0x54,0x70,0x3c,0x10,0x20,0x8d,
- 0x01,0x04,0x54,0xd3,0x07,0x38,0x20,0x8d,
- 0x01,0x04,0x54,0xed,0x07,0xf9,0x20,0x8d,
- 0x01,0x04,0x55,0x17,0x33,0xb1,0x20,0x8d,
- 0x01,0x04,0x55,0x18,0x91,0xc6,0x20,0x8d,
- 0x01,0x04,0x55,0xb8,0x8a,0x6c,0x20,0x8d,
+ 0x01,0x04,0x54,0xd7,0x38,0x77,0x20,0x8d,
+ 0x01,0x04,0x54,0xe2,0xf3,0xaf,0x20,0x8d,
+ 0x01,0x04,0x54,0xf5,0x0e,0x49,0x20,0x8d,
+ 0x01,0x04,0x54,0xfc,0x9d,0x5a,0x47,0x9d,
+ 0x01,0x04,0x54,0xff,0xf4,0x3d,0x20,0x8d,
+ 0x01,0x04,0x55,0x17,0x18,0x7b,0x20,0x8d,
+ 0x01,0x04,0x55,0x34,0xb9,0x1d,0x21,0xda,
+ 0x01,0x04,0x55,0x3a,0x78,0xc9,0x20,0x8d,
+ 0x01,0x04,0x55,0x5d,0x60,0x12,0x20,0x8d,
+ 0x01,0x04,0x55,0xa5,0x08,0xc5,0x20,0x8d,
+ 0x01,0x04,0x55,0xad,0xa5,0x42,0x20,0x8d,
+ 0x01,0x04,0x55,0xb8,0x8f,0x69,0x20,0x8d,
+ 0x01,0x04,0x55,0xbf,0x4a,0x67,0x20,0x8d,
0x01,0x04,0x55,0xc2,0xee,0x86,0x20,0x8d,
0x01,0x04,0x55,0xc3,0x36,0x6e,0x20,0x8d,
+ 0x01,0x04,0x55,0xc3,0xc4,0x8e,0x20,0x8d,
+ 0x01,0x04,0x55,0xd0,0x45,0x0b,0x20,0x8d,
+ 0x01,0x04,0x55,0xd0,0x45,0x15,0x20,0x8d,
0x01,0x04,0x55,0xd0,0x47,0x24,0x20,0x8d,
0x01,0x04,0x55,0xd0,0x47,0x27,0x20,0x8d,
- 0x01,0x04,0x55,0xd6,0x88,0x2d,0x20,0x8d,
+ 0x01,0x04,0x55,0xd6,0x76,0x47,0x20,0x8d,
0x01,0x04,0x55,0xd6,0xa1,0xfc,0x20,0x8d,
- 0x01,0x04,0x55,0xe3,0xf5,0x80,0x20,0x8d,
- 0x01,0x04,0x56,0x12,0x22,0xf3,0x20,0x8d,
- 0x01,0x04,0x56,0x14,0x32,0xaa,0x20,0x8d,
- 0x01,0x04,0x56,0x31,0x69,0x5a,0x20,0x8d,
- 0x01,0x04,0x56,0x4c,0x07,0x84,0x20,0x8d,
+ 0x01,0x04,0x55,0xd8,0x20,0x49,0x20,0x8d,
+ 0x01,0x04,0x55,0xfe,0x62,0xdd,0x20,0x8d,
+ 0x01,0x04,0x56,0x3a,0x0b,0x98,0x20,0x8d,
+ 0x01,0x04,0x56,0x5f,0x08,0xf9,0x20,0x8d,
0x01,0x04,0x56,0x64,0x1a,0xbc,0x20,0x8d,
0x01,0x04,0x56,0x6a,0x8f,0x8f,0xd8,0x4d,
- 0x01,0x04,0x56,0x78,0x3a,0x42,0x20,0x8d,
+ 0x01,0x04,0x56,0x7c,0x91,0xb8,0x20,0x8d,
0x01,0x04,0x56,0x85,0xfb,0xef,0x22,0xc5,
- 0x01,0x04,0x56,0x95,0x08,0x17,0x22,0xc5,
- 0x01,0x04,0x57,0x4e,0xc5,0xea,0x20,0x8d,
+ 0x01,0x04,0x57,0x4f,0x5e,0xdd,0x20,0x8d,
0x01,0x04,0x57,0x78,0x08,0x05,0x4e,0x28,
- 0x01,0x04,0x57,0x79,0x25,0x9c,0x20,0x8d,
- 0x01,0x04,0x58,0x52,0xb5,0x2c,0x20,0x8d,
- 0x01,0x04,0x58,0x57,0x5d,0x34,0x06,0x9b,
- 0x01,0x04,0x58,0x62,0xeb,0x86,0x20,0x8d,
- 0x01,0x04,0x58,0x88,0xbb,0xd6,0x20,0x8d,
- 0x01,0x04,0x58,0x93,0xf4,0xfa,0x20,0x8d,
- 0x01,0x04,0x58,0x94,0x99,0x94,0x20,0x8d,
+ 0x01,0x04,0x57,0x7d,0x9d,0xdc,0x20,0x8d,
+ 0x01,0x04,0x58,0x09,0x4c,0x85,0x20,0x8d,
+ 0x01,0x04,0x58,0x5a,0xb8,0x44,0x20,0x8d,
+ 0x01,0x04,0x58,0x97,0x65,0x0e,0x13,0x88,
+ 0x01,0x04,0x58,0x97,0x65,0xfd,0x13,0x88,
+ 0x01,0x04,0x58,0xc6,0x5c,0x2f,0x20,0x8d,
+ 0x01,0x04,0x58,0xd0,0x73,0x46,0x20,0x8d,
+ 0x01,0x04,0x58,0xd2,0x0f,0x18,0x20,0x8d,
0x01,0x04,0x58,0xd4,0x2d,0xa6,0x20,0x8d,
- 0x01,0x04,0x58,0xd4,0x37,0x8a,0x20,0x8d,
- 0x01,0x04,0x59,0x26,0x60,0x99,0x24,0x39,
- 0x01,0x04,0x59,0x2f,0xa1,0x87,0x20,0x8d,
- 0x01,0x04,0x59,0x58,0x3e,0xbe,0x20,0x8d,
- 0x01,0x04,0x59,0x9e,0x20,0x2c,0x20,0x8d,
- 0x01,0x04,0x59,0xa3,0x91,0xf0,0x20,0x8d,
- 0x01,0x04,0x59,0xa3,0xf9,0xea,0x0e,0x59,
- 0x01,0x04,0x59,0xb0,0xc4,0x50,0x20,0x8d,
- 0x01,0x04,0x59,0xd8,0x15,0x60,0x20,0x8d,
- 0x01,0x04,0x5a,0x54,0xe3,0xff,0x20,0x8d,
+ 0x01,0x04,0x59,0x66,0xce,0xee,0x20,0x8d,
+ 0x01,0x04,0x59,0x67,0x6f,0x22,0x20,0x8d,
+ 0x01,0x04,0x59,0x72,0x8f,0x71,0x20,0x8d,
+ 0x01,0x04,0x59,0x86,0x3e,0x4a,0x20,0x8d,
+ 0x01,0x04,0x59,0x98,0x08,0xe7,0x20,0x8d,
+ 0x01,0x04,0x59,0xa1,0x1a,0x4e,0x20,0x8d,
+ 0x01,0x04,0x59,0xcf,0x83,0x13,0x20,0x8d,
+ 0x01,0x04,0x59,0xf8,0xc1,0xe5,0x20,0x8d,
+ 0x01,0x04,0x5a,0x03,0x30,0x3e,0x20,0x8d,
+ 0x01,0x04,0x5a,0x92,0x79,0x61,0x20,0x8d,
0x01,0x04,0x5a,0x92,0x82,0xd6,0x20,0x8d,
+ 0x01,0x04,0x5a,0xc4,0xa9,0x3a,0x20,0x8d,
0x01,0x04,0x5a,0xfa,0x09,0x01,0x20,0x8d,
0x01,0x04,0x5b,0x5d,0xc2,0x9a,0x20,0x8d,
- 0x01,0x04,0x5b,0x6a,0xbc,0xe5,0x20,0x8d,
0x01,0x04,0x5b,0x7e,0x28,0x6d,0x20,0x8d,
- 0x01,0x04,0x5b,0x89,0x7f,0x7b,0x20,0x8d,
- 0x01,0x04,0x5b,0x93,0xe8,0x62,0x20,0x8d,
- 0x01,0x04,0x5b,0x98,0x7b,0x12,0x20,0x8d,
- 0x01,0x04,0x5b,0xb2,0x11,0x78,0x20,0x8d,
0x01,0x04,0x5b,0xcc,0x63,0xb2,0x20,0x8d,
- 0x01,0x04,0x5b,0xdf,0xaf,0x0e,0x20,0x8d,
- 0x01,0x04,0x5c,0x2a,0x6e,0xf2,0x20,0x8d,
- 0x01,0x04,0x5c,0x35,0x5a,0x54,0x20,0x8d,
- 0x01,0x04,0x5c,0xdd,0x9b,0xe4,0x20,0x8d,
+ 0x01,0x04,0x5b,0xcc,0x95,0x05,0x20,0x8d,
+ 0x01,0x04,0x5b,0xce,0x11,0xc3,0x20,0x8d,
+ 0x01,0x04,0x5b,0xd1,0x33,0x83,0x20,0x8d,
+ 0x01,0x04,0x5b,0xd7,0x5b,0xfe,0x20,0x8d,
+ 0x01,0x04,0x5c,0x5b,0x1b,0x3c,0x20,0x8d,
+ 0x01,0x04,0x5c,0xdd,0x14,0xe8,0x20,0x8d,
+ 0x01,0x04,0x5c,0xff,0x55,0x1f,0x20,0x8d,
+ 0x01,0x04,0x5d,0x04,0x65,0x25,0x20,0x8d,
+ 0x01,0x04,0x5d,0x2e,0x51,0x05,0x20,0x8d,
0x01,0x04,0x5d,0x39,0x51,0xa2,0x20,0x8d,
+ 0x01,0x04,0x5d,0x49,0x27,0xc4,0x20,0x8d,
+ 0x01,0x04,0x5d,0x5a,0x52,0xe2,0x20,0x8d,
0x01,0x04,0x5d,0x5f,0x58,0x0d,0x20,0x8d,
- 0x01,0x04,0x5d,0x67,0x0d,0x01,0x20,0x8d,
0x01,0x04,0x5d,0x7b,0xb4,0xa4,0x20,0x8d,
- 0x01,0x04,0x5d,0xbe,0x75,0x1a,0x20,0x8d,
- 0x01,0x04,0x5e,0x69,0x7d,0xf0,0x20,0x8d,
- 0x01,0x04,0x5e,0x6e,0x17,0xd7,0x20,0x8d,
+ 0x01,0x04,0x5d,0xbd,0x91,0xa9,0x20,0x8d,
+ 0x01,0x04,0x5e,0x11,0xb9,0x6b,0x20,0x8d,
+ 0x01,0x04,0x5e,0x4b,0xc6,0x78,0x20,0x8d,
+ 0x01,0x04,0x5e,0x72,0xc4,0xa9,0x20,0x8d,
+ 0x01,0x04,0x5e,0x8e,0xd5,0xfa,0xd8,0xf8,
0x01,0x04,0x5e,0x9a,0x9f,0x63,0x20,0x8d,
- 0x01,0x04,0x5e,0xbd,0xa1,0x77,0x20,0x8d,
- 0x01,0x04,0x5e,0xcb,0xff,0x46,0x20,0x8d,
- 0x01,0x04,0x5e,0xe8,0xad,0x5d,0x20,0x8d,
- 0x01,0x04,0x5f,0x4f,0x7a,0x63,0x20,0x8d,
- 0x01,0x04,0x5f,0x50,0x01,0x6e,0x20,0x8d,
- 0x01,0x04,0x5f,0x53,0x49,0x1f,0x20,0x8d,
+ 0x01,0x04,0x5e,0x9e,0xf6,0xb7,0x20,0x8d,
+ 0x01,0x04,0x5e,0xef,0x91,0x20,0x20,0x8d,
+ 0x01,0x04,0x5f,0x1f,0x0c,0x16,0x20,0x8d,
+ 0x01,0x04,0x5f,0x1f,0xc4,0x0f,0x20,0x8d,
0x01,0x04,0x5f,0x6e,0x85,0xdf,0x20,0x8d,
0x01,0x04,0x5f,0x6e,0xea,0x5d,0x20,0x8d,
- 0x01,0x04,0x5f,0xa4,0x41,0xc2,0x20,0x8d,
- 0x01,0x04,0x5f,0xa5,0x08,0xb6,0x20,0x8d,
- 0x01,0x04,0x5f,0xae,0xdb,0x65,0x20,0x8d,
+ 0x01,0x04,0x5f,0xa1,0x0c,0x2d,0x20,0x8d,
0x01,0x04,0x5f,0xbf,0x82,0x64,0x20,0x8d,
+ 0x01,0x04,0x5f,0xd0,0x9e,0xa1,0x20,0x8d,
+ 0x01,0x04,0x5f,0xd5,0x91,0xda,0x20,0x8d,
0x01,0x04,0x5f,0xd6,0x35,0x9a,0x20,0x8d,
- 0x01,0x04,0x5f,0xd7,0xcd,0xb4,0x20,0x8d,
- 0x01,0x04,0x60,0x2b,0x82,0xea,0x20,0x8d,
- 0x01,0x04,0x62,0x19,0xc9,0x1f,0x20,0x8d,
- 0x01,0x04,0x62,0x80,0xf7,0xb6,0x20,0x8d,
- 0x01,0x04,0x62,0xab,0x15,0x81,0x20,0x8d,
- 0x01,0x04,0x63,0x93,0x87,0xa1,0x20,0x8d,
- 0x01,0x04,0x65,0x64,0xa3,0x76,0x20,0x87,
- 0x01,0x04,0x66,0x84,0xf5,0x10,0x20,0x8d,
- 0x01,0x04,0x66,0xb6,0xcc,0x60,0x20,0x8d,
- 0x01,0x04,0x66,0xb6,0xeb,0xf5,0x20,0x8d,
+ 0x01,0x04,0x5f,0xd6,0x35,0xa0,0x20,0x8d,
+ 0x01,0x04,0x60,0x2c,0x9c,0xc7,0x20,0x8d,
+ 0x01,0x04,0x61,0x4b,0x91,0x0c,0x20,0x8d,
+ 0x01,0x04,0x66,0x84,0xc0,0x8d,0x20,0x8d,
0x01,0x04,0x67,0x0e,0xf5,0xfa,0x20,0x8d,
- 0x01,0x04,0x67,0x2f,0xc0,0x0f,0x20,0x8d,
- 0x01,0x04,0x67,0x54,0x54,0xfa,0x20,0x8f,
- 0x01,0x04,0x67,0x63,0xa8,0x82,0x20,0x8d,
+ 0x01,0x04,0x67,0x55,0x26,0xcd,0x20,0x8d,
+ 0x01,0x04,0x67,0x58,0x5c,0x4e,0x20,0x8c,
+ 0x01,0x04,0x67,0x63,0xa8,0x64,0x20,0x8d,
0x01,0x04,0x67,0x63,0xa8,0x8c,0x20,0x8d,
- 0x01,0x04,0x67,0xc6,0xc0,0x0e,0x4e,0x28,
- 0x01,0x04,0x67,0xe8,0x68,0xe3,0x20,0x8d,
- 0x01,0x04,0x68,0x8f,0x02,0xc3,0x20,0x8d,
- 0x01,0x04,0x68,0xac,0xeb,0xe3,0x20,0x8d,
+ 0x01,0x04,0x67,0x63,0xaa,0xd2,0x20,0x8d,
+ 0x01,0x04,0x67,0x63,0xaa,0xdc,0x20,0x8d,
+ 0x01,0x04,0x67,0x64,0x2c,0x46,0x20,0x8d,
+ 0x01,0x04,0x67,0xb2,0xec,0x1b,0x20,0x8d,
+ 0x01,0x04,0x67,0xd1,0x0c,0x90,0x20,0x8d,
+ 0x01,0x04,0x68,0x3b,0x93,0x0f,0x20,0x8d,
+ 0x01,0x04,0x68,0x81,0xab,0x79,0x20,0x8d,
+ 0x01,0x04,0x68,0xc8,0x41,0xea,0x20,0x8d,
0x01,0x04,0x68,0xee,0xdc,0xc7,0x20,0x8d,
- 0x01,0x04,0x6b,0x0b,0x73,0x44,0x20,0x8d,
+ 0x01,0x04,0x68,0xf4,0x49,0x06,0x20,0x8d,
+ 0x01,0x04,0x6a,0x47,0x77,0xe6,0x20,0x8d,
0x01,0x04,0x6b,0xad,0xa6,0x2b,0x20,0x8d,
- 0x01,0x04,0x6c,0x04,0xd4,0x53,0x20,0x8d,
- 0x01,0x04,0x6d,0x88,0x49,0x61,0x20,0x8d,
- 0x01,0x04,0x6d,0xad,0x62,0x17,0x20,0x8d,
- 0x01,0x04,0x6d,0xbe,0x44,0x74,0x20,0x8d,
- 0x01,0x04,0x6d,0xeb,0xf6,0x3c,0x20,0x8d,
+ 0x01,0x04,0x6c,0xa1,0x16,0x4e,0x20,0x8d,
+ 0x01,0x04,0x6c,0xae,0x3f,0xea,0x20,0x8d,
+ 0x01,0x04,0x6d,0x63,0x3f,0x9f,0x20,0x8d,
+ 0x01,0x04,0x6d,0x69,0x28,0xf7,0x20,0x8d,
+ 0x01,0x04,0x6d,0x6b,0xb9,0x82,0x20,0x8d,
+ 0x01,0x04,0x6d,0x6e,0xef,0x04,0x20,0x8d,
+ 0x01,0x04,0x6d,0xad,0x29,0x2b,0x20,0x8d,
+ 0x01,0x04,0x6d,0xec,0x5a,0x75,0x20,0x8d,
0x01,0x04,0x6d,0xf8,0xce,0x0d,0x20,0x8d,
- 0x01,0x04,0x6e,0x0c,0x40,0x60,0x20,0x8d,
+ 0x01,0x04,0x6d,0xff,0x6a,0xce,0x20,0x8d,
+ 0x01,0x04,0x6f,0x5a,0x8c,0x17,0x20,0x8d,
0x01,0x04,0x6f,0x5a,0x8c,0x2e,0x20,0x8d,
- 0x01,0x04,0x6f,0x5a,0x9f,0xb8,0xc3,0x51,
- 0x01,0x04,0x71,0x6b,0xc9,0x83,0x20,0x8d,
+ 0x01,0x04,0x6f,0x5a,0x9f,0xf6,0x20,0x8d,
+ 0x01,0x04,0x70,0x76,0xbc,0x32,0x20,0x8d,
0x01,0x04,0x73,0x2f,0x8d,0xfa,0x22,0xb5,
0x01,0x04,0x74,0x3a,0xab,0x43,0x20,0x8d,
- 0x01,0x04,0x74,0x57,0x39,0xda,0x20,0x8d,
- 0x01,0x04,0x74,0xca,0xa1,0x38,0x20,0x8d,
- 0x01,0x04,0x75,0x33,0x9f,0x82,0x20,0x8d,
- 0x01,0x04,0x76,0x67,0x7e,0x8c,0x6e,0xad,
- 0x01,0x04,0x79,0x2d,0xbe,0xd2,0x20,0x8d,
- 0x01,0x04,0x79,0x63,0xc1,0x19,0x20,0x8d,
- 0x01,0x04,0x7a,0x70,0x94,0x99,0x20,0x93,
- 0x01,0x04,0x7a,0x94,0x87,0xea,0x20,0x8d,
+ 0x01,0x04,0x76,0x5c,0x6b,0x6c,0x20,0x8d,
+ 0x01,0x04,0x77,0x2a,0x37,0xcb,0x20,0x8d,
+ 0x01,0x04,0x78,0x4f,0x47,0x48,0x20,0x8d,
+ 0x01,0x04,0x79,0x63,0xf0,0x57,0x20,0x8d,
+ 0x01,0x04,0x7b,0x3c,0xd5,0xc0,0x20,0x8d,
+ 0x01,0x04,0x7c,0x9c,0x9e,0x64,0x20,0x8d,
+ 0x01,0x04,0x7c,0xde,0x7b,0xee,0x20,0x8d,
+ 0x01,0x04,0x7d,0xb2,0x06,0x74,0x20,0x8d,
0x01,0x04,0x80,0x00,0xbe,0x1a,0x20,0x8d,
0x01,0x04,0x80,0x41,0xc2,0x88,0x20,0x8d,
+ 0x01,0x04,0x81,0x0d,0xbd,0xd4,0x20,0x8d,
0x01,0x04,0x81,0x7e,0xac,0x73,0x20,0x8d,
- 0x01,0x04,0x81,0xe2,0x7d,0x0a,0x20,0x8d,
+ 0x01,0x04,0x81,0x92,0x34,0xae,0x20,0x8d,
+ 0x01,0x04,0x82,0x2c,0xa8,0xca,0x20,0x8d,
+ 0x01,0x04,0x83,0xa1,0x50,0xa6,0x20,0x8d,
0x01,0x04,0x83,0xbc,0x28,0xbf,0x20,0x8d,
0x01,0x04,0x86,0xc3,0xb9,0x34,0x20,0x8d,
- 0x01,0x04,0x87,0xb4,0x2c,0x3d,0x20,0x8d,
- 0x01,0x04,0x88,0x34,0x72,0x7b,0x20,0x8d,
+ 0x01,0x04,0x87,0x86,0xee,0x2f,0x20,0x8d,
+ 0x01,0x04,0x87,0xb4,0xda,0x3a,0x20,0x8d,
+ 0x01,0x04,0x87,0xb5,0xd7,0xed,0x20,0x8d,
+ 0x01,0x04,0x88,0x1d,0x6d,0xb4,0x20,0x8d,
+ 0x01,0x04,0x88,0x20,0xee,0x06,0x20,0x8d,
0x01,0x04,0x88,0x38,0xaa,0x60,0x20,0x8d,
- 0x01,0x04,0x89,0x74,0xd5,0x8f,0x20,0x8d,
+ 0x01,0x04,0x89,0x19,0x26,0x6c,0x20,0x8d,
0x01,0x04,0x89,0xe2,0x22,0x2e,0x20,0x8d,
- 0x01,0x04,0x8a,0x2b,0xe9,0x39,0x20,0x8d,
+ 0x01,0x04,0x8a,0xcf,0xd3,0x6a,0x20,0x8d,
0x01,0x04,0x8b,0x82,0x29,0x52,0x20,0x8d,
+ 0x01,0x04,0x8b,0x99,0xff,0x6b,0x20,0x8d,
0x01,0x04,0x8c,0xbe,0x0c,0x81,0x20,0x8d,
- 0x01,0x04,0x8e,0x04,0x69,0x4d,0x20,0x8d,
0x01,0x04,0x8e,0x36,0xb5,0xda,0x20,0x8d,
- 0x01,0x04,0x8f,0xb1,0xe7,0xf7,0x20,0x8d,
+ 0x01,0x04,0x8f,0xb1,0xe5,0x95,0x20,0x8d,
0x01,0x04,0x8f,0xb2,0x40,0x0a,0x20,0x8d,
- 0x01,0x04,0x90,0x22,0xa1,0x41,0x47,0x9d,
- 0x01,0x04,0x92,0x04,0x7c,0x86,0x20,0x8d,
+ 0x01,0x04,0x90,0x18,0xf5,0xb7,0x20,0x8d,
+ 0x01,0x04,0x90,0x7e,0x82,0xb2,0x20,0x8d,
+ 0x01,0x04,0x92,0x04,0x7c,0x81,0x20,0x8d,
+ 0x01,0x04,0x92,0x47,0x45,0x67,0x20,0x8d,
0x01,0x04,0x92,0x53,0x38,0x45,0x20,0x8d,
- 0x01,0x04,0x92,0x5a,0xc1,0x44,0x20,0x8d,
- 0x01,0x04,0x92,0xc4,0x37,0x9c,0x70,0xa1,
- 0x01,0x04,0x94,0x42,0x32,0x32,0x20,0x8f,
- 0x01,0x04,0x94,0xfb,0x01,0x14,0x20,0x97,
- 0x01,0x04,0x97,0x30,0x5f,0xd4,0x20,0x8d,
+ 0x01,0x04,0x93,0xc2,0xb1,0xa5,0x20,0x8d,
+ 0x01,0x04,0x95,0x5a,0xd6,0x4e,0x20,0x8d,
+ 0x01,0x04,0x95,0x66,0x9d,0x9c,0x20,0x8d,
+ 0x01,0x04,0x97,0xf8,0x9c,0x37,0x20,0x8d,
0x01,0x04,0x97,0xfc,0xc1,0xf5,0x20,0x8d,
- 0x01,0x04,0x98,0x2c,0x89,0x53,0x20,0x8d,
- 0x01,0x04,0x98,0x73,0xbf,0xc4,0x20,0x8d,
- 0x01,0x04,0x9a,0xdd,0x1f,0x56,0x20,0x8d,
+ 0x01,0x04,0x99,0x5c,0x5d,0x72,0x20,0x8d,
+ 0x01,0x04,0x9a,0xd3,0x06,0x02,0x20,0x8d,
0x01,0x04,0x9c,0x11,0x67,0x02,0x1f,0x98,
- 0x01,0x04,0x9d,0x8a,0x14,0x16,0x20,0x8d,
+ 0x01,0x04,0x9c,0x92,0xb1,0xdd,0x20,0x8d,
+ 0x01,0x04,0x9d,0x83,0x8f,0xad,0x20,0x8d,
0x01,0x04,0x9e,0x3a,0xbc,0x25,0x20,0x8d,
- 0x01,0x04,0x9e,0x8c,0xd1,0x4f,0x20,0x8d,
+ 0x01,0x04,0x9e,0xf8,0x27,0xef,0x20,0x8d,
0x01,0x04,0x9f,0x59,0xe6,0x80,0x20,0x8d,
- 0x01,0x04,0x9f,0xf6,0x19,0x34,0x20,0x8d,
- 0x01,0x04,0xa0,0x14,0x3b,0xfa,0x20,0xf1,
- 0x01,0x04,0xa2,0x00,0xea,0xbe,0x20,0x8d,
- 0x01,0x04,0xa2,0x3e,0x1a,0xda,0x20,0x8d,
- 0x01,0x04,0xa2,0xfa,0xbc,0xc2,0x20,0x8d,
- 0x01,0x04,0xa2,0xfb,0x46,0x52,0x20,0x8d,
- 0x01,0x04,0xa3,0x9e,0xce,0xff,0x20,0x8d,
- 0x01,0x04,0xa4,0x44,0x69,0x69,0x20,0x8d,
+ 0x01,0x04,0x9f,0xc4,0x03,0xef,0x20,0x8d,
+ 0x01,0x04,0x9f,0xe0,0xbd,0xfa,0x20,0x8d,
+ 0x01,0x04,0xa0,0x48,0x33,0x9a,0x20,0x8d,
+ 0x01,0x04,0xa1,0x1d,0xec,0x37,0x20,0x8d,
+ 0x01,0x04,0xa1,0x61,0x77,0xa6,0x20,0x8d,
+ 0x01,0x04,0xa1,0xf6,0x0b,0xe6,0x20,0x8d,
+ 0x01,0x04,0xa2,0x3e,0x12,0xe2,0x20,0x8d,
+ 0x01,0x04,0xa2,0xfa,0x7b,0xb3,0x20,0x8d,
+ 0x01,0x04,0xa2,0xfa,0xbf,0xde,0x20,0x8d,
+ 0x01,0x04,0xa2,0xfe,0x76,0x14,0x20,0x8d,
+ 0x01,0x04,0xa3,0xac,0x51,0x46,0x20,0x8d,
+ 0x01,0x04,0xa4,0x5a,0x2f,0x08,0x20,0x8d,
0x01,0x04,0xa5,0xe4,0xae,0x75,0x20,0x8d,
- 0x01,0x04,0xa6,0x3e,0x52,0x67,0x80,0x03,
- 0x01,0x04,0xa6,0x46,0x31,0x1a,0x20,0x8d,
- 0x01,0x04,0xa6,0x4e,0xf1,0x09,0x20,0x8d,
- 0x01,0x04,0xa6,0x4e,0xf1,0x19,0x20,0x8d,
- 0x01,0x04,0xa7,0x47,0x49,0xf4,0x20,0x8d,
- 0x01,0x04,0xa7,0xb3,0x93,0x9b,0x20,0x8d,
+ 0x01,0x04,0xa6,0x46,0x91,0x97,0x20,0x8d,
0x01,0x04,0xa8,0x5b,0xee,0x08,0x20,0x8d,
+ 0x01,0x04,0xaa,0xfd,0x0b,0x19,0x20,0x8d,
+ 0x01,0x04,0xab,0x67,0xaa,0x73,0x20,0x8d,
+ 0x01,0x04,0xac,0x5d,0xa6,0x87,0x20,0x8d,
+ 0x01,0x04,0xac,0x67,0xd9,0xec,0x20,0x8d,
0x01,0x04,0xac,0x69,0x15,0xd8,0x20,0x8d,
- 0x01,0x04,0xac,0x75,0x69,0x5f,0x20,0x8d,
- 0x01,0x04,0xad,0x17,0x67,0x1e,0x1f,0x40,
- 0x01,0x04,0xad,0xcd,0x5c,0x97,0xd6,0x15,
- 0x01,0x04,0xad,0xcd,0x5c,0x9a,0xd6,0x15,
- 0x01,0x04,0xad,0xcd,0x5c,0x9d,0xd6,0x15,
+ 0x01,0x04,0xac,0x70,0x99,0x5f,0x20,0x8d,
+ 0x01,0x04,0xad,0x03,0xda,0x5b,0x20,0x8d,
+ 0x01,0x04,0xad,0x0c,0x77,0x85,0x20,0x8d,
+ 0x01,0x04,0xad,0x22,0x7f,0xb5,0x20,0x8d,
+ 0x01,0x04,0xad,0x4c,0x7b,0xad,0x20,0x8d,
+ 0x01,0x04,0xad,0xb0,0xc6,0x44,0x20,0x8d,
0x01,0x04,0xad,0xd0,0x98,0xda,0x20,0x8d,
0x01,0x04,0xad,0xf1,0xe3,0xf3,0x20,0x8d,
- 0x01,0x04,0xae,0x03,0x04,0xe8,0x20,0x8d,
- 0x01,0x04,0xae,0x11,0x0b,0x16,0x20,0x8d,
- 0x01,0x04,0xae,0x58,0xf1,0xa7,0x20,0x8d,
- 0x01,0x04,0xae,0x72,0x66,0x29,0x20,0x8d,
+ 0x01,0x04,0xad,0xf6,0x1b,0x07,0x20,0x8d,
+ 0x01,0x04,0xad,0xff,0xf0,0xcd,0x20,0x8d,
+ 0x01,0x04,0xae,0x1e,0x2f,0x0f,0x20,0x8d,
0x01,0x04,0xae,0x72,0xfa,0x56,0x20,0x8d,
+ 0x01,0x04,0xae,0x8a,0x23,0xe5,0x20,0x8d,
0x01,0x04,0xae,0x8e,0xbf,0x88,0x20,0x8d,
- 0x01,0x04,0xaf,0x27,0x48,0x57,0x20,0x8d,
- 0x01,0x04,0xb0,0x0c,0x10,0x87,0x20,0x8d,
- 0x01,0x04,0xb0,0x25,0x17,0x1e,0x20,0x8d,
- 0x01,0x04,0xb0,0x3e,0xb3,0xdd,0x20,0x8d,
+ 0x01,0x04,0xb0,0x0a,0x8f,0xbe,0x20,0x8d,
0x01,0x04,0xb0,0x4a,0x88,0xed,0x20,0x8d,
- 0x01,0x04,0xb0,0x63,0x06,0xe2,0x20,0x8d,
+ 0x01,0x04,0xb0,0x76,0xdc,0x1d,0x20,0x8d,
+ 0x01,0x04,0xb0,0x7e,0x74,0x07,0x20,0x8d,
+ 0x01,0x04,0xb0,0x7e,0xa7,0x0a,0x20,0x8d,
0x01,0x04,0xb0,0xd4,0xb9,0x99,0x20,0x8d,
+ 0x01,0x04,0xb0,0xeb,0xd1,0xba,0x20,0x8d,
0x01,0x04,0xb1,0x51,0xec,0x75,0x20,0x8d,
- 0x01,0x04,0xb2,0x13,0x6a,0x1a,0x20,0x8d,
- 0x01,0x04,0xb2,0x15,0x76,0xb2,0x20,0x8d,
- 0x01,0x04,0xb2,0x21,0xe8,0x45,0x20,0x8d,
- 0x01,0x04,0xb2,0x4f,0x54,0x8b,0x20,0x8d,
+ 0x01,0x04,0xb1,0x59,0xcd,0x46,0x20,0x8d,
+ 0x01,0x04,0xb2,0x30,0xa8,0x0c,0x20,0x8d,
0x01,0x04,0xb2,0x7c,0xa2,0xd1,0x20,0x8d,
- 0x01,0x04,0xb2,0x84,0x02,0xf6,0x20,0x8d,
- 0x01,0x04,0xb2,0x96,0x60,0x2e,0x20,0x8d,
- 0x01,0x04,0xb2,0xa2,0xd4,0x2c,0x20,0x8d,
- 0x01,0x04,0xb2,0xc1,0xe2,0x78,0x20,0x8d,
+ 0x01,0x04,0xb2,0x9f,0x62,0x85,0x20,0x8d,
+ 0x01,0x04,0xb2,0xc4,0x59,0xd1,0x20,0x8d,
0x01,0x04,0xb2,0xec,0x89,0x3f,0x20,0x8d,
+ 0x01,0x04,0xb2,0xfc,0x7b,0x18,0x20,0x8d,
+ 0x01,0x04,0xb3,0x2b,0xaa,0xba,0x20,0x8d,
0x01,0x04,0xb4,0x96,0x2e,0xbb,0x20,0x8d,
- 0x01,0x04,0xb5,0xa4,0xd2,0xe4,0x21,0x52,
- 0x01,0x04,0xb7,0x6e,0xdc,0xd2,0x76,0x5d,
- 0x01,0x04,0xb8,0x5f,0x3a,0xa6,0x20,0x90,
- 0x01,0x04,0xb8,0xa4,0x93,0x52,0xa1,0x75,
- 0x01,0x04,0xb8,0xab,0xd0,0x6d,0x20,0x8d,
- 0x01,0x04,0xb9,0x11,0x8f,0xdc,0x20,0x8d,
- 0x01,0x04,0xb9,0x15,0xd9,0x31,0x20,0x8d,
+ 0x01,0x04,0xb5,0x75,0x80,0x8c,0x20,0x8d,
+ 0x01,0x04,0xb8,0x13,0x13,0x10,0x20,0x8d,
+ 0x01,0x04,0xb9,0x15,0xd9,0x30,0x20,0x8d,
0x01,0x04,0xb9,0x19,0x30,0xb8,0x20,0x8d,
- 0x01,0x04,0xb9,0x1c,0x60,0x10,0x20,0x8d,
0x01,0x04,0xb9,0x1f,0x88,0xf6,0x20,0x8d,
+ 0x01,0x04,0xb9,0x34,0x5d,0x2d,0x20,0x8d,
0x01,0x04,0xb9,0x40,0x74,0x0f,0x20,0x8d,
0x01,0x04,0xb9,0x44,0xf9,0x5b,0x20,0x8d,
- 0x01,0x04,0xb9,0x6c,0xf7,0xbe,0x20,0x8d,
- 0x01,0x04,0xb9,0x8d,0x3c,0x24,0x20,0x8d,
- 0x01,0x04,0xb9,0x94,0x03,0xe3,0x20,0x8d,
+ 0x01,0x04,0xb9,0x62,0x36,0x14,0x20,0x8d,
+ 0x01,0x04,0xb9,0x6b,0x53,0x37,0x20,0x8d,
+ 0x01,0x04,0xb9,0x8c,0xfd,0xa9,0x20,0x8d,
0x01,0x04,0xb9,0x94,0x91,0x4a,0x20,0x8d,
- 0x01,0x04,0xb9,0x9f,0x14,0x8f,0x20,0x8d,
+ 0x01,0x04,0xb9,0xa5,0xaa,0x13,0x20,0x8d,
0x01,0x04,0xb9,0xa7,0x71,0x3b,0x20,0x8d,
0x01,0x04,0xb9,0xb9,0x1a,0x8d,0x1f,0xaf,
- 0x01,0x04,0xb9,0xbd,0x84,0xb2,0xe1,0xb4,
- 0x01,0x04,0xb9,0xcc,0xc5,0x70,0x20,0x8d,
+ 0x01,0x04,0xb9,0xc5,0xa3,0x88,0x20,0x8d,
+ 0x01,0x04,0xb9,0xd1,0x0c,0x4c,0x20,0x8d,
0x01,0x04,0xb9,0xd1,0x46,0x11,0x20,0x8d,
- 0x01,0x04,0xb9,0xdc,0x9c,0xc1,0x20,0x8d,
- 0x01,0x04,0xb9,0xee,0x81,0x71,0x20,0x8d,
+ 0x01,0x04,0xb9,0xe3,0x9c,0xe2,0x20,0x8d,
+ 0x01,0x04,0xb9,0xe9,0xbd,0xd2,0x20,0x8d,
0x01,0x04,0xb9,0xef,0xdd,0x05,0x20,0x8d,
- 0x01,0x04,0xb9,0xf4,0xd9,0x27,0x20,0x8d,
+ 0x01,0x04,0xb9,0xf4,0x64,0x6a,0x20,0x8d,
0x01,0x04,0xb9,0xfe,0x61,0xa4,0x20,0x8d,
0x01,0x04,0xba,0x21,0xa7,0x0b,0x20,0x8d,
+ 0x01,0x04,0xba,0xb0,0x62,0x25,0x20,0x8d,
+ 0x01,0x04,0xba,0xf9,0xd9,0x19,0x20,0x8d,
+ 0x01,0x04,0xba,0xfa,0x5f,0x84,0x20,0x8d,
0x01,0x04,0xbc,0x20,0x0e,0x1f,0x20,0x8e,
- 0x01,0x04,0xbc,0x2a,0x28,0xea,0x47,0x9d,
- 0x01,0x04,0xbc,0x86,0x08,0x24,0x20,0x8d,
+ 0x01,0x04,0xbc,0x23,0xa7,0x0e,0x20,0x8d,
+ 0x01,0x04,0xbc,0x44,0x2d,0x8f,0x20,0x8d,
+ 0x01,0x04,0xbc,0x75,0xc8,0xd4,0x20,0x8d,
0x01,0x04,0xbc,0x8a,0x58,0x0e,0x20,0x8d,
- 0x01,0x04,0xbc,0x9c,0x6e,0xef,0x20,0x8d,
- 0x01,0x04,0xbc,0xa5,0xf4,0x8f,0x20,0x8d,
- 0x01,0x04,0xbc,0xd5,0x44,0x26,0x20,0x8d,
- 0x01,0x04,0xbc,0xd6,0x81,0x41,0x4e,0x2c,
- 0x01,0x04,0xbc,0xf2,0x0f,0x4a,0x20,0x8d,
- 0x01,0x04,0xbc,0xf4,0x04,0x4e,0x20,0x8d,
- 0x01,0x04,0xbd,0x27,0x06,0x52,0x20,0x8d,
- 0x01,0x04,0xbd,0xcf,0x2e,0x20,0x20,0x8d,
- 0x01,0x04,0xbd,0xd4,0x79,0x4a,0x20,0x8d,
- 0x01,0x04,0xc0,0x03,0x0b,0x14,0x20,0x8d,
- 0x01,0x04,0xc0,0x41,0xaa,0x0f,0x20,0x8d,
+ 0x01,0x04,0xbc,0x97,0xed,0x9e,0x20,0x8d,
+ 0x01,0x04,0xbc,0x9a,0xec,0x31,0x20,0x8d,
+ 0x01,0x04,0xbd,0x7b,0xb1,0x80,0x20,0x8d,
+ 0x01,0x04,0xbe,0x7b,0x1b,0x0b,0x20,0x8d,
+ 0x01,0x04,0xbe,0x91,0x7f,0xfe,0x20,0x8d,
+ 0x01,0x04,0xc0,0x45,0x35,0x4d,0x20,0x8d,
0x01,0x04,0xc0,0x92,0x89,0x2c,0x20,0x8d,
- 0x01,0x04,0xc0,0xb6,0x9d,0x77,0x20,0x8d,
- 0x01,0x04,0xc0,0xbb,0x6d,0x8d,0x20,0x8d,
- 0x01,0x04,0xc0,0xe3,0x50,0x53,0x20,0x8d,
- 0x01,0x04,0xc1,0x0a,0xcb,0x17,0x20,0x8e,
- 0x01,0x04,0xc1,0x20,0x7f,0xa0,0xe4,0x6d,
- 0x01,0x04,0xc1,0x20,0x7f,0xa2,0xe4,0x6d,
- 0x01,0x04,0xc1,0x3a,0xc4,0xd4,0x20,0x8d,
- 0x01,0x04,0xc1,0x6a,0x1d,0x6a,0x20,0x8d,
- 0x01,0x04,0xc1,0x8a,0x9a,0x2b,0x20,0x8d,
- 0x01,0x04,0xc1,0xb2,0xaa,0xe8,0x20,0x8d,
+ 0x01,0x04,0xc0,0xde,0x18,0x36,0x20,0x8d,
+ 0x01,0x04,0xc0,0xde,0x93,0x8d,0x20,0x8d,
+ 0x01,0x04,0xc1,0x20,0x7f,0xa2,0xee,0x29,
+ 0x01,0x04,0xc1,0x6f,0xc6,0xbb,0x1f,0xaf,
0x01,0x04,0xc1,0xc4,0x25,0x3e,0x20,0x8d,
- 0x01,0x04,0xc1,0xde,0x82,0x0e,0x20,0x8d,
- 0x01,0x04,0xc1,0xea,0x32,0xe3,0x20,0x8d,
- 0x01,0x04,0xc2,0x0e,0xf6,0xcd,0x20,0x8d,
- 0x01,0x04,0xc2,0x87,0x87,0x45,0x20,0x8d,
+ 0x01,0x04,0xc2,0x0d,0x50,0xb9,0x3c,0x46,
0x01,0x04,0xc2,0x93,0x71,0xc9,0x20,0x8d,
0x01,0x04,0xc2,0xa5,0x1e,0x14,0x20,0x8d,
- 0x01,0x04,0xc2,0xdb,0x3e,0x17,0x20,0x8d,
+ 0x01,0x04,0xc2,0xbf,0xef,0x62,0x20,0x8d,
0x01,0x04,0xc3,0x38,0x3f,0x04,0x20,0x8d,
- 0x01,0x04,0xc3,0x86,0xb7,0xbc,0x20,0x8d,
- 0x01,0x04,0xc3,0xd0,0x67,0x1e,0x20,0xfc,
- 0x01,0x04,0xc3,0xd0,0x67,0x1f,0x20,0xfc,
+ 0x01,0x04,0xc3,0x38,0x3f,0x0a,0x20,0x8d,
+ 0x01,0x04,0xc3,0x7b,0xef,0xb9,0x20,0x8d,
+ 0x01,0x04,0xc3,0x8c,0xe2,0x9a,0x20,0x8d,
0x01,0x04,0xc6,0x01,0xe7,0x06,0x20,0x8d,
- 0x01,0x04,0xc6,0x0c,0x0e,0x88,0x20,0x8d,
- 0x01,0x04,0xc6,0x54,0xed,0x46,0x20,0x8d,
- 0x01,0x04,0xc6,0xb2,0x78,0x05,0x1f,0xb0,
- 0x01,0x04,0xc7,0x30,0x5c,0xb8,0x20,0x8d,
- 0x01,0x04,0xc7,0x44,0xc7,0x13,0x20,0x8d,
- 0x01,0x04,0xc7,0xb6,0xb8,0xcc,0x20,0x8d,
- 0x01,0x04,0xc7,0xbd,0xf2,0x8d,0x20,0x8d,
+ 0x01,0x04,0xc6,0x94,0x70,0x1b,0x20,0x8d,
+ 0x01,0x04,0xc7,0x7e,0xea,0xed,0x20,0x8d,
+ 0x01,0x04,0xc7,0xc1,0xae,0xad,0x20,0x8d,
0x01,0x04,0xc7,0xf7,0x07,0xd0,0x20,0x8d,
- 0x01,0x04,0xc8,0x7a,0xb5,0x25,0x20,0x8d,
+ 0x01,0x04,0xc8,0x7a,0xb5,0x2e,0x20,0x8d,
0x01,0x04,0xc9,0xbf,0x06,0x67,0x20,0x8d,
- 0x01,0x04,0xca,0x6b,0xdb,0x82,0x20,0x8d,
+ 0x01,0x04,0xc9,0xd4,0x24,0xd1,0x20,0x8d,
+ 0x01,0x04,0xc9,0xdd,0xea,0xc8,0x20,0x8d,
0x01,0x04,0xca,0x6c,0xd3,0x87,0x20,0x8d,
- 0x01,0x04,0xcb,0x5e,0x21,0x70,0x20,0x8d,
+ 0x01,0x04,0xca,0xa9,0x11,0xb2,0x20,0x8d,
+ 0x01,0x04,0xca,0xb1,0x18,0x8c,0x20,0x8d,
0x01,0x04,0xcb,0x82,0x30,0x75,0x22,0xb5,
0x01,0x04,0xcb,0x84,0x5e,0xc4,0x20,0x8d,
- 0x01,0x04,0xcb,0xa2,0x0d,0xb5,0x20,0x8c,
- 0x01,0x04,0xcc,0xbf,0xc9,0x2b,0x20,0x8d,
- 0x01,0x04,0xcc,0xe5,0x0a,0x5a,0x20,0x8d,
0x01,0x04,0xcd,0xb2,0x29,0x7c,0x20,0x8d,
- 0x01,0x04,0xce,0x37,0xb2,0x9d,0x20,0x8d,
- 0x01,0x04,0xce,0x7e,0xcb,0x08,0x20,0x8d,
- 0x01,0x04,0xce,0xae,0x73,0x60,0x20,0x8d,
+ 0x01,0x04,0xce,0x48,0xc9,0xe4,0x20,0x8d,
+ 0x01,0x04,0xce,0xc0,0xcb,0x00,0x20,0x8d,
0x01,0x04,0xce,0xdf,0x99,0x34,0x20,0x8d,
- 0x01,0x04,0xcf,0xbc,0x9f,0x19,0x20,0x8d,
+ 0x01,0x04,0xcf,0x86,0xd8,0x91,0x20,0x8e,
+ 0x01,0x04,0xcf,0xbc,0x9a,0x32,0x20,0x8d,
0x01,0x04,0xcf,0xe5,0x2e,0x50,0x20,0x8d,
+ 0x01,0x04,0xcf,0xff,0xc1,0x2f,0x20,0x8d,
+ 0x01,0x04,0xd0,0x68,0x5c,0x4a,0x20,0x8d,
0x01,0x04,0xd1,0x3a,0x91,0x9d,0x20,0x8d,
- 0x01,0x04,0xd1,0x7e,0x51,0x93,0x20,0x8d,
- 0x01,0x04,0xd1,0x91,0x3f,0x96,0x20,0x8d,
- 0x01,0x04,0xd1,0xd1,0x0a,0x1e,0x20,0x8d,
+ 0x01,0x04,0xd1,0x3a,0x9e,0xe8,0x20,0x8f,
+ 0x01,0x04,0xd1,0x8d,0x2b,0xf3,0x20,0x8d,
+ 0x01,0x04,0xd1,0xe2,0x8e,0x3e,0x20,0x8d,
0x01,0x04,0xd1,0xed,0x7f,0xe3,0x20,0x8d,
- 0x01,0x04,0xd4,0x63,0xe2,0x24,0x23,0x3c,
- 0x01,0x04,0xd4,0xb9,0x56,0x54,0x20,0x8d,
+ 0x01,0x04,0xd1,0xed,0x85,0x36,0x20,0x8d,
+ 0x01,0x04,0xd3,0xf8,0x5a,0x32,0x20,0x8d,
+ 0x01,0x04,0xd4,0x15,0x12,0x4e,0x20,0x8d,
+ 0x01,0x04,0xd4,0x22,0xe1,0x76,0x20,0x8d,
+ 0x01,0x04,0xd4,0x33,0x92,0x89,0x20,0x8d,
0x01,0x04,0xd4,0xe3,0xd3,0x57,0x20,0x8d,
+ 0x01,0x04,0xd5,0x00,0x45,0x4c,0x20,0x8d,
0x01,0x04,0xd5,0x05,0x24,0x3a,0x20,0x8d,
- 0x01,0x04,0xd5,0x59,0xec,0xdb,0x20,0x8d,
- 0x01,0x04,0xd5,0x5d,0x91,0xb7,0x20,0x8d,
+ 0x01,0x04,0xd5,0x2f,0x40,0x69,0x20,0x8d,
+ 0x01,0x04,0xd5,0x59,0x87,0x97,0x20,0x8d,
+ 0x01,0x04,0xd5,0x8d,0x9a,0xc9,0x20,0x8d,
+ 0x01,0x04,0xd5,0x9f,0xc6,0x2d,0x20,0x8d,
+ 0x01,0x04,0xd5,0xb8,0xf4,0x18,0x20,0x8d,
0x01,0x04,0xd5,0xd6,0x42,0xb6,0x20,0x8d,
- 0x01,0x04,0xd8,0x29,0xf9,0xb2,0x20,0x8d,
+ 0x01,0x04,0xd5,0xe2,0x7b,0x4c,0x20,0x8d,
0x01,0x04,0xd8,0x92,0xfb,0x08,0x20,0x8d,
- 0x01,0x04,0xd8,0xf9,0x46,0x16,0x20,0x8d,
- 0x01,0x04,0xd9,0x0b,0xf0,0x04,0x20,0x8d,
- 0x01,0x04,0xd9,0x0f,0xb2,0x07,0x20,0x8d,
- 0x01,0x04,0xd9,0x18,0xe9,0x74,0x20,0x8d,
- 0x01,0x04,0xd9,0x40,0x94,0x62,0xc8,0xc9,
+ 0x01,0x04,0xd8,0xba,0xee,0x0e,0x20,0x8d,
+ 0x01,0x04,0xd9,0x05,0x96,0x72,0x20,0x8d,
+ 0x01,0x04,0xd9,0x0f,0xb2,0x0b,0x20,0x8d,
+ 0x01,0x04,0xd9,0x18,0xef,0x6d,0x20,0x8d,
+ 0x01,0x04,0xd9,0x40,0x2f,0x8a,0x20,0x8d,
+ 0x01,0x04,0xd9,0x49,0x50,0x68,0x20,0x8d,
+ 0x01,0x04,0xd9,0x4f,0xb5,0x26,0x20,0x8d,
+ 0x01,0x04,0xd9,0x5c,0x37,0xf6,0x20,0x8d,
0x01,0x04,0xd9,0x71,0x79,0xa9,0x20,0x8d,
+ 0x01,0x04,0xd9,0x73,0x74,0xfa,0x20,0x8d,
+ 0x01,0x04,0xd9,0x9b,0xf4,0xaa,0x20,0x8d,
0x01,0x04,0xd9,0xaa,0x7c,0xaa,0x20,0x8d,
0x01,0x04,0xdc,0x84,0x87,0x36,0x20,0x8d,
- 0x01,0x04,0xdc,0xdd,0x3a,0x19,0x20,0x8d,
0x01,0x04,0xdc,0xe9,0xb2,0xc7,0x20,0x8d,
- 0x01,0x04,0xdd,0xdb,0x61,0x69,0x07,0xd1,
- 0x02,0x10,0x20,0x01,0x16,0x08,0x00,0x1b,0x00,0xf9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x67,0x7b,
+ 0x01,0x04,0xde,0x9a,0x6f,0x2e,0x20,0x8d,
0x02,0x10,0x20,0x01,0x16,0x20,0x05,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x19,0xf0,0x60,0x01,0x39,0xaa,0x54,0x00,0x03,0xff,0xfe,0xf0,0x09,0x16,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x19,0xf0,0x80,0x01,0x0f,0x71,0x54,0x00,0x04,0xff,0xfe,0x10,0x6a,0x63,0x20,0x8d,
0x02,0x10,0x20,0x01,0x1b,0xc0,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x20,0x8d,
- 0x02,0x10,0x20,0x01,0x04,0x70,0x1f,0x0a,0x08,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x1c,0x02,0x01,0x1e,0x35,0x00,0xdf,0x25,0x63,0x21,0x82,0x60,0xd9,0xbe,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x10,0x04,0x1b,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x93,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x02,0x03,0x37,0x39,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x02,0x03,0xaa,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x02,0x03,0xbb,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x00,0x02,0xbf,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x03,0x03,0x65,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x06,0x02,0x44,0x93,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x00,0x08,0xb9,0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xd0,0x00,0x0a,0x69,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x41,0xf0,0x00,0x00,0x00,0x00,0x00,0x62,0x69,0x74,0x63,0x6f,0x69,0x6e,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x44,0xb8,0x02,0x56,0x5d,0x11,0x02,0x16,0x3e,0xff,0xfe,0x39,0xd5,0xd4,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x04,0x70,0x1b,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x04,0x70,0x1f,0x07,0x08,0x03,0x02,0x0c,0x29,0xff,0xfe,0x2d,0x58,0x79,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x04,0x70,0x1f,0x15,0x01,0x06,0xe2,0xd5,0x5e,0xff,0xfe,0x42,0x7a,0xe5,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x04,0x70,0x1f,0x15,0x0c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x04,0x70,0x00,0x26,0x04,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x7c,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x04,0x70,0x75,0xe9,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x20,0x8d,
0x02,0x10,0x20,0x01,0x04,0x70,0xde,0x5a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xec,0x24,0x75,
- 0x02,0x10,0x20,0x01,0x4b,0x98,0x0d,0xc0,0x00,0x45,0x02,0x16,0x3e,0xff,0xfe,0xa2,0x95,0xcd,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4b,0xa0,0xba,0xbe,0x05,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4b,0xa0,0xff,0xff,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4d,0xd0,0x35,0x64,0x00,0x00,0x30,0xb7,0x1d,0x7b,0x6f,0xec,0x4c,0x5c,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4d,0xd0,0x35,0x64,0x00,0x00,0x08,0x8e,0xb4,0xff,0x2a,0xd0,0x69,0x9b,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4d,0xd0,0x35,0x64,0x00,0x00,0x9c,0x1c,0xcc,0x31,0x9f,0xe8,0x55,0x05,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4d,0xd0,0x35,0x64,0x00,0x00,0xa0,0xc4,0xd4,0x1f,0x04,0xc4,0x1b,0xb0,0x20,0x8d,
0x02,0x10,0x20,0x01,0x4d,0xd0,0x35,0x64,0x00,0x00,0xfd,0x76,0xc1,0xd3,0x18,0x54,0x5b,0xd9,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4d,0xd0,0x35,0x64,0x00,0x01,0x00,0x00,0x00,0x00,0x76,0x76,0x80,0x90,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4d,0xd0,0x35,0x64,0x00,0x01,0xb9,0x77,0xbd,0x71,0x46,0x12,0x8e,0x40,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4d,0xd0,0xaf,0x0e,0x35,0x64,0x00,0x00,0x00,0x00,0x00,0x69,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x4d,0xd0,0xaf,0x0e,0x35,0x64,0x00,0x00,0x00,0x00,0x00,0x69,0x00,0x90,0x20,0x8d,
0x02,0x10,0x20,0x01,0x4d,0xe8,0xb1,0xb2,0x00,0x01,0x00,0x00,0xde,0xad,0xbe,0xef,0x00,0x07,0x20,0x8d,
0x02,0x10,0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x40,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x91,0x20,0x8d,
- 0x02,0x10,0x20,0x01,0x06,0x48,0x28,0x00,0x01,0x31,0x4b,0x1f,0xf6,0xfc,0x20,0xf7,0xf9,0x9f,0x20,0x8d,
- 0x02,0x10,0x20,0x01,0x06,0x78,0x0c,0xc8,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x88,0x4e,0x28,
+ 0x02,0x10,0x20,0x01,0x06,0x78,0x0a,0xcc,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
0x02,0x10,0x20,0x01,0x06,0x7c,0x26,0xb4,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x20,0x8d,
- 0x02,0x10,0x20,0x01,0x06,0x7c,0x2d,0xb8,0x00,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x06,0x7c,0x2d,0xb8,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x07,0xc0,0x23,0x10,0x00,0x00,0xf8,0x16,0x3e,0xff,0xfe,0x0d,0x4a,0xb6,0x20,0x8d,
0x02,0x10,0x20,0x01,0x07,0xc0,0x23,0x10,0x00,0x00,0xf8,0x16,0x3e,0xff,0xfe,0x6c,0x4f,0x58,0x20,0x8d,
- 0x02,0x10,0x20,0x01,0x08,0x18,0xea,0x1b,0x76,0x00,0xf0,0x53,0xaa,0xde,0xf4,0x7b,0xb7,0x01,0x20,0x8d,
- 0x02,0x10,0x20,0x01,0x08,0xf1,0x14,0x04,0x37,0x00,0x8e,0x49,0x71,0x5a,0x2e,0x09,0xb6,0x34,0x24,0xe4,
- 0x02,0x10,0x20,0x01,0x09,0x85,0x55,0xa0,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
- 0x02,0x10,0x20,0x01,0x09,0x99,0x02,0x70,0x2c,0x2c,0x0c,0x8b,0x3a,0x20,0x3f,0x2f,0x31,0x8f,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x08,0x61,0x32,0x46,0x0a,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x0b,0x07,0x02,0xe6,0x38,0xd7,0xba,0x27,0xeb,0xff,0xfe,0x60,0x3d,0xc1,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x0b,0x07,0x64,0x61,0x78,0x11,0x04,0x89,0xd2,0xda,0x0e,0x07,0x1a,0xf7,0x20,0x8d,
0x02,0x10,0x20,0x01,0x0b,0x07,0x0a,0xc9,0x44,0x2b,0x79,0xd6,0xbb,0xbe,0xb3,0x7c,0xa7,0x83,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x0b,0xc8,0x16,0x00,0x00,0x00,0x02,0x08,0xa2,0xff,0xfe,0x0c,0x8a,0x2e,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x0b,0xc8,0x32,0x3c,0x00,0xff,0xa6,0x34,0x38,0x4f,0x18,0x49,0xf4,0xbc,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x0b,0xc8,0x32,0x3c,0x00,0xff,0xd2,0x17,0xc2,0xff,0xfe,0x07,0x2c,0xd9,0x20,0x8d,
+ 0x02,0x10,0x20,0x01,0x0b,0xc8,0x3b,0xec,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
0x02,0x10,0x20,0x02,0x2f,0x5b,0xa5,0xf9,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0x5b,0xa5,0xf9,0x22,0xb5,
- 0x02,0x10,0x20,0x02,0xb6,0xff,0x3d,0xca,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0xff,0x3d,0xca,0x6e,0xcc,
+ 0x02,0x10,0x20,0x03,0x00,0xcb,0x87,0x13,0x61,0x02,0xaa,0xa1,0x59,0xff,0xfe,0x57,0x77,0x79,0x20,0x8d,
+ 0x02,0x10,0x20,0x03,0x00,0xe0,0x37,0x0e,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x20,0x8d,
+ 0x02,0x10,0x20,0x03,0x00,0xf6,0x3f,0x10,0x67,0x00,0x4c,0x9f,0x76,0x20,0x83,0x24,0xd4,0xa7,0x20,0x8d,
0x02,0x10,0x24,0x00,0x24,0x10,0xce,0xa2,0x0d,0x00,0x41,0xbc,0xc9,0xea,0x86,0x1b,0x51,0xee,0x20,0x8d,
+ 0x02,0x10,0x24,0x00,0x24,0x11,0xa3,0xe1,0x49,0x00,0x25,0x68,0x68,0x4b,0x0e,0x99,0x71,0x20,0x20,0x8d,
+ 0x02,0x10,0x24,0x00,0x24,0x11,0xa3,0xe1,0x49,0x00,0x29,0x87,0xb8,0x8f,0x61,0xe0,0x84,0xfa,0x20,0x8d,
0x02,0x10,0x24,0x00,0x3b,0x00,0x00,0x20,0x00,0x0c,0xba,0xcb,0x29,0xff,0xfe,0xab,0x88,0x86,0x20,0x8d,
+ 0x02,0x10,0x24,0x01,0xb1,0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x10,0x20,0x8d,
+ 0x02,0x10,0x24,0x01,0xb1,0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x20,0x20,0x8d,
+ 0x02,0x10,0x24,0x01,0xb1,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x01,0x00,0x20,0x8d,
+ 0x02,0x10,0x24,0x01,0xb1,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x01,0x30,0x20,0x8d,
0x02,0x10,0x24,0x01,0xd0,0x02,0x39,0x02,0x07,0x00,0xd7,0x2c,0x5e,0x22,0x4e,0x95,0x38,0x9d,0x20,0x8d,
- 0x02,0x10,0x24,0x03,0x62,0x00,0x88,0xa0,0xfb,0x17,0xf5,0xf2,0xd8,0xb5,0xb7,0xba,0xf4,0xd3,0x20,0x8d,
- 0x02,0x10,0x24,0x05,0x98,0x00,0xb9,0x10,0x5f,0x8e,0x18,0x30,0xf6,0x30,0x2c,0xc6,0x88,0xfb,0x20,0x8d,
- 0x02,0x10,0x24,0x05,0x98,0x00,0xb9,0x70,0xc6,0x4c,0x10,0x9f,0x74,0xe7,0xae,0x5f,0x87,0xc7,0x20,0x8d,
- 0x02,0x10,0x24,0x05,0xaa,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x20,0x8d,
- 0x02,0x10,0x24,0x07,0x88,0x00,0xbc,0x61,0x22,0x02,0xd6,0x3d,0x7e,0xff,0xfe,0x6c,0xdc,0x36,0x20,0x8d,
- 0x02,0x10,0x24,0x08,0x82,0x48,0x70,0x04,0xf8,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x3c,0x20,0x8d,
+ 0x02,0x10,0x24,0x04,0x44,0x08,0x67,0x52,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x99,0x20,0x8d,
+ 0x02,0x10,0x24,0x04,0x7a,0x85,0x41,0x61,0x2b,0x00,0x49,0xa1,0x42,0x7a,0x0f,0xac,0x34,0x09,0x20,0x8d,
+ 0x02,0x10,0x24,0x05,0x98,0x00,0xb9,0x72,0xab,0x58,0x0c,0x05,0xe9,0x38,0x26,0x7e,0x02,0x71,0x20,0x8d,
+ 0x02,0x10,0x24,0x06,0xda,0x11,0x01,0x69,0x0b,0x03,0x32,0xb5,0xf9,0x01,0x9f,0x7c,0x3e,0x4b,0x20,0x8d,
+ 0x02,0x10,0x24,0x06,0xda,0x14,0x03,0x35,0xb6,0x01,0xce,0xb7,0xb4,0xfc,0xa8,0x55,0xf3,0xa5,0x20,0x8d,
+ 0x02,0x10,0x24,0x06,0xda,0x1e,0x0a,0x4e,0x8a,0x03,0x2a,0xad,0x49,0x6b,0x76,0x8d,0xe4,0x97,0x20,0x8d,
+ 0x02,0x10,0x24,0x07,0x88,0x00,0xbc,0x61,0x22,0x02,0xa0,0xc6,0x01,0x07,0x50,0x2b,0x4e,0x3b,0x20,0x8d,
0x02,0x10,0x24,0x09,0x00,0x10,0xca,0x20,0x1d,0xf0,0x02,0x24,0xe8,0xff,0xfe,0x1f,0x60,0xd9,0x20,0x8d,
- 0x02,0x10,0x24,0x0b,0x00,0x11,0x43,0xa1,0xbd,0x00,0xe5,0x89,0xf8,0xa7,0x04,0x9b,0x3b,0x86,0x20,0x8d,
- 0x02,0x10,0x24,0x0d,0x00,0x1a,0x07,0x91,0x34,0x00,0xd6,0x5d,0x64,0xff,0xfe,0x28,0x92,0x7e,0x20,0x8d,
- 0x02,0x10,0x24,0x0d,0x00,0x1a,0x07,0x91,0x34,0x00,0xd6,0x81,0xd7,0xff,0xfe,0xf6,0xa2,0x1e,0x27,0x42,
- 0x02,0x10,0x26,0x00,0x17,0x00,0x5b,0x2b,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x17,0x00,0x22,0xf1,0x64,0x1f,0x00,0xe8,0x39,0xc8,0xeb,0x1d,0xa1,0xeb,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x17,0x00,0x9c,0x5d,0x0e,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x17,0x00,0x9c,0x5d,0x0e,0xd0,0xd0,0xd6,0x01,0xd9,0x5c,0xc2,0xab,0x47,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x17,0x02,0x1c,0xe0,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x1f,0x14,0x04,0x0e,0xe3,0x01,0xd1,0x55,0xaa,0x3a,0x77,0xbe,0x96,0x0e,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x1f,0x16,0x0a,0x08,0xb9,0x01,0x1a,0xfa,0xef,0x4e,0x4c,0xe7,0x2b,0xa4,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x1f,0x1c,0x02,0xd3,0x24,0x03,0x5b,0xac,0x3f,0xc6,0x65,0x13,0x7a,0x63,0x20,0x8d,
0x02,0x10,0x26,0x00,0x21,0x04,0x10,0x03,0xc5,0xab,0xdc,0x5e,0x90,0xff,0xfe,0x18,0x1d,0x08,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x92,0xff,0xfe,0x92,0x27,0x45,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x92,0xff,0xfe,0xcf,0x61,0xb6,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x93,0xff,0xfe,0xb3,0x01,0xb6,0x20,0x8d,
0x02,0x10,0x26,0x00,0x3c,0x00,0xe0,0x02,0x2e,0x32,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x14,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x3c,0x02,0x00,0x00,0x00,0x00,0xf0,0x3c,0x92,0xff,0xfe,0x5d,0x09,0xfb,0x20,0x8d,
+ 0x02,0x10,0x26,0x00,0x40,0x40,0x28,0x54,0x5e,0x00,0xc6,0xe9,0x84,0xff,0xfe,0x46,0x0e,0xe8,0x21,0xda,
+ 0x02,0x10,0x26,0x00,0x6c,0x54,0x71,0x00,0x1a,0xd1,0xbd,0xdf,0x55,0x0e,0x91,0xbe,0xf9,0xe1,0x20,0x8d,
0x02,0x10,0x26,0x00,0x88,0x05,0x24,0x00,0x01,0x4e,0x12,0xdd,0xb1,0xff,0xfe,0xf2,0x30,0x13,0x20,0x8d,
+ 0x02,0x10,0x26,0x01,0x01,0x84,0x03,0x00,0x0b,0xde,0x3c,0x29,0x8e,0x94,0x1b,0xa8,0xfd,0xe3,0x20,0x8d,
+ 0x02,0x10,0x26,0x01,0x01,0x8c,0x80,0x80,0x30,0x0f,0x02,0x19,0xd1,0xff,0xfe,0x75,0xdc,0x2f,0x20,0x8d,
+ 0x02,0x10,0x26,0x01,0x01,0x8d,0x46,0x00,0x43,0xf1,0x20,0xe7,0xb3,0xff,0xfe,0xcf,0x0a,0x99,0x20,0x8d,
+ 0x02,0x10,0x26,0x01,0x01,0x8d,0x87,0x01,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x20,0x8d,
+ 0x02,0x10,0x26,0x01,0x02,0x46,0x4d,0x7f,0x9e,0x28,0xf3,0x21,0x36,0xca,0x7a,0x71,0xc6,0x87,0x20,0x8d,
+ 0x02,0x10,0x26,0x01,0x06,0x40,0xc2,0x01,0x96,0x0d,0x86,0xeb,0xf2,0x7d,0x66,0xa2,0xf2,0xc1,0x20,0x8d,
+ 0x02,0x10,0x26,0x02,0x02,0x41,0x75,0xd1,0x2b,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x40,0x20,0x8d,
0x02,0x10,0x26,0x02,0xff,0xb8,0x00,0x00,0x00,0x00,0x02,0x08,0x00,0x72,0x00,0x57,0x02,0x00,0x20,0x8d,
- 0x02,0x10,0x26,0x03,0x30,0x1f,0x1e,0xbf,0xe0,0x00,0xe2,0x3f,0x49,0xff,0xfe,0xe7,0x74,0x31,0x20,0x8d,
- 0x02,0x10,0x26,0x03,0x60,0x81,0x18,0x00,0x66,0x00,0x16,0xdd,0xa9,0xff,0xfe,0xee,0xb2,0xf3,0x20,0x8d,
- 0x02,0x10,0x26,0x04,0x13,0x80,0x10,0x00,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
- 0x02,0x10,0x26,0x04,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x06,0x1f,0xb0,
- 0x02,0x10,0x26,0x04,0x55,0x00,0xc1,0x34,0x40,0x00,0x72,0x85,0xc2,0xff,0xfe,0x4a,0xe1,0x43,0x80,0x1d,
- 0x02,0x10,0x26,0x04,0x55,0x00,0xc1,0x34,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xfc,0x80,0x1d,
+ 0x02,0x10,0x26,0x03,0x30,0x04,0x06,0xa1,0x38,0x00,0x85,0x1f,0x58,0x4d,0x7a,0xba,0xaf,0xfb,0x20,0x8d,
+ 0x02,0x10,0x26,0x03,0x30,0x04,0x06,0xa1,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x02,0x20,0x8d,
+ 0x02,0x10,0x26,0x03,0x30,0x04,0x07,0x0d,0x14,0x00,0x85,0x32,0x29,0x00,0xce,0x6f,0xac,0xdf,0x20,0x8d,
+ 0x02,0x10,0x26,0x03,0x30,0x04,0x07,0x45,0x09,0x00,0xf0,0xd7,0x55,0x6a,0x0a,0x8c,0xce,0xd5,0x20,0x8d,
+ 0x02,0x10,0x26,0x03,0x60,0x80,0xc0,0x00,0x5d,0x8a,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x4f,0x20,0x8d,
+ 0x02,0x10,0x26,0x03,0x80,0x00,0xd1,0x00,0x89,0x91,0xcc,0x29,0xcc,0xff,0xfe,0x42,0x30,0x0c,0x20,0x8d,
+ 0x02,0x10,0x26,0x03,0x80,0x80,0x1f,0x07,0x6f,0xdd,0x7d,0xe2,0xd9,0x69,0x78,0xc9,0xb7,0xea,0x20,0x8d,
+ 0x02,0x10,0x26,0x03,0x80,0x80,0x73,0x00,0x05,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xea,0x20,0x8d,
+ 0x02,0x10,0x26,0x03,0x80,0xa0,0x07,0x03,0x40,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0x01,0x80,0x00,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0x3d,0x08,0x00,0x00,0x00,0x05,0xd9,0x41,0x4b,0x03,0xa0,0x93,0x13,0x1b,0x20,0x8d,
0x02,0x10,0x26,0x04,0x7c,0x00,0x01,0x20,0x00,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,0xeb,0x24,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0x0a,0x00,0x00,0x21,0x30,0x43,0xbf,0x6a,0x53,0x5e,0xdf,0xeb,0x5b,0x7b,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x1c,0xe7,0x40,0x01,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x1d,0x44,0xe0,0x01,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd0,0x00,0x00,0x00,0x00,0x26,0x1f,0x60,0x01,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0xa8,0x80,0x04,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x07,0xe2,0xe0,0x01,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0xa8,0x80,0x00,0x04,0x01,0xd0,0x00,0x00,0x00,0x00,0x00,0x14,0x30,0x00,0x20,0x8d,
+ 0x02,0x10,0x26,0x04,0xa8,0x80,0x00,0x04,0x01,0xd0,0x00,0x00,0x00,0x00,0x00,0xe5,0xb0,0x00,0x20,0x8d,
0x02,0x10,0x26,0x05,0x64,0x00,0x00,0x30,0xf2,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
0x02,0x10,0x26,0x05,0x6f,0x80,0x00,0x00,0x00,0x07,0xfc,0x1b,0xcc,0xff,0xfe,0x8a,0xd8,0x22,0x20,0x8d,
+ 0x02,0x10,0x26,0x05,0xa1,0x40,0x20,0x76,0x82,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x26,0x05,0xa1,0x40,0x30,0x07,0x12,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
0x02,0x10,0x26,0x05,0xae,0x00,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03,0x20,0x8d,
0x02,0x10,0x26,0x05,0xc0,0x00,0x2a,0x0a,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x20,0x8d,
- 0x02,0x10,0x26,0x05,0xf7,0x00,0x00,0xc0,0x08,0x27,0x02,0x25,0x90,0xff,0xfe,0xe3,0x34,0xa6,0x20,0x8d,
+ 0x02,0x10,0x26,0x07,0x1a,0x00,0x00,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x11,0x7c,0x4d,0x20,0x8d,
+ 0x02,0x10,0x26,0x07,0x53,0x00,0x02,0x03,0x12,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
0x02,0x10,0x26,0x07,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x14,0x25,0xb5,0x20,0x8d,
- 0x02,0x10,0x26,0x07,0xf2,0xf8,0xad,0x40,0x0b,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
- 0x02,0x10,0x26,0x07,0xfa,0x18,0x3a,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x8d,
- 0x02,0x10,0x26,0x20,0x01,0x1c,0x50,0x01,0x11,0x18,0xd2,0x67,0xe5,0xff,0xfe,0xe9,0xe6,0x73,0x20,0x8d,
- 0x02,0x10,0x26,0x20,0x01,0x1c,0x50,0x01,0x21,0x99,0xd2,0x67,0xe5,0xff,0xfe,0xe9,0xe6,0x73,0x20,0x8d,
+ 0x02,0x10,0x26,0x07,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x21,0x9c,0x2f,0x20,0x8d,
+ 0x02,0x10,0x26,0x07,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x21,0xbf,0x32,0x20,0x8d,
+ 0x02,0x10,0x26,0x07,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x33,0x4d,0x1b,0x20,0x8d,
+ 0x02,0x10,0x26,0x07,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x3d,0x04,0x01,0x20,0x8d,
+ 0x02,0x10,0x26,0x07,0xf2,0xc0,0xe1,0xc2,0x00,0x69,0x12,0xc3,0x7b,0xff,0xfe,0x4d,0x94,0x31,0x20,0x8d,
+ 0x02,0x10,0x26,0x07,0xf2,0xc0,0xe1,0xc2,0x00,0x69,0xec,0xb2,0x6e,0x88,0x9f,0x33,0x50,0x57,0x20,0x8d,
0x02,0x10,0x26,0x20,0x00,0x06,0x20,0x03,0x01,0x05,0x02,0xd8,0x61,0xff,0xfe,0x0f,0x08,0x53,0x20,0x8d,
0x02,0x10,0x26,0x20,0x00,0x6e,0xa0,0x00,0x00,0x01,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x20,0x8d,
- 0x02,0x10,0x28,0x03,0xcf,0x00,0x0a,0xf8,0xf2,0x00,0xb8,0x9e,0xcf,0x34,0x92,0xc7,0x2d,0x26,0x20,0x8d,
- 0x02,0x10,0x28,0x04,0x01,0x4c,0x65,0xd1,0x40,0x2c,0xbc,0x53,0xbf,0x5d,0x06,0x8a,0x21,0x36,0x20,0x8d,
- 0x02,0x10,0x28,0x04,0x07,0xf1,0xe7,0x83,0xd4,0x01,0x66,0x1c,0x67,0xff,0xfe,0xba,0x55,0x47,0x20,0x8d,
- 0x02,0x10,0x28,0x04,0x0d,0x57,0x55,0x37,0x48,0x00,0x02,0x1e,0x67,0xff,0xfe,0xa8,0xd7,0x98,0x20,0x8d,
- 0x02,0x10,0x28,0x04,0x0d,0x57,0x55,0x37,0x48,0x00,0x36,0x15,0x9e,0xff,0xfe,0x23,0xd6,0x10,0x20,0x8d,
- 0x02,0x10,0x28,0x06,0x02,0xf0,0x20,0x80,0x06,0x2a,0x08,0x6f,0x1a,0x01,0xc4,0x4f,0x17,0x94,0x20,0x8d,
- 0x02,0x10,0x2a,0x00,0x10,0x28,0x83,0x82,0xbf,0x22,0x5f,0x7f,0xb7,0x8f,0x27,0x37,0x77,0x39,0x20,0x8d,
+ 0x02,0x10,0x26,0x20,0x00,0xa6,0x20,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0xd5,0x70,0x20,0x8d,
+ 0x02,0x10,0x26,0x20,0x00,0xa6,0x20,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x2a,0x20,0x8d,
+ 0x02,0x10,0x26,0x20,0x00,0xa6,0x20,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x05,0x16,0x31,0x20,0x8d,
+ 0x02,0x10,0x26,0x20,0x00,0xa6,0x20,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0c,0xe6,0x34,0x20,0x8d,
+ 0x02,0x10,0x28,0x00,0x00,0x40,0x00,0x33,0x08,0xab,0xa0,0xe7,0xb2,0x15,0xfc,0x83,0x5c,0x31,0x20,0x8d,
+ 0x02,0x10,0x28,0x00,0x0b,0xf0,0x01,0x49,0x0f,0x4b,0xf8,0xdf,0x8d,0x7d,0x80,0x1b,0xe2,0x5e,0x20,0x8d,
+ 0x02,0x10,0x28,0x04,0x01,0x4c,0x01,0x98,0x80,0xd5,0x76,0x03,0x41,0xd1,0xd3,0xfc,0xe7,0x97,0x20,0x8d,
+ 0x02,0x10,0x28,0x04,0x01,0x4d,0xae,0x81,0x82,0x7b,0x99,0xa8,0x1e,0x3f,0x6d,0xb2,0x29,0xdb,0x20,0x8d,
+ 0x02,0x10,0x28,0x04,0x0d,0x57,0x55,0x37,0x48,0x00,0x3e,0x7c,0x3f,0xff,0xfe,0x7b,0x80,0xaa,0x20,0x8d,
0x02,0x10,0x2a,0x00,0x12,0xe0,0x01,0x01,0x00,0x99,0x02,0x0c,0x29,0xff,0xfe,0x29,0xd0,0x3f,0x20,0x8d,
0x02,0x10,0x2a,0x00,0x13,0x28,0xe1,0x01,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x63,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x13,0x98,0x00,0x04,0x2a,0x03,0x02,0x15,0x5d,0xff,0xfe,0xd6,0x10,0x33,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x13,0x98,0x00,0x04,0x2a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x03,0x20,0x8d,
0x02,0x10,0x2a,0x00,0x16,0x30,0x00,0x10,0x10,0x03,0x00,0x00,0x0b,0x19,0xb0,0x0b,0xba,0xbe,0x20,0x8d,
0x02,0x10,0x2a,0x00,0x17,0x68,0x20,0x01,0x00,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x6a,0x20,0x8d,
0x02,0x10,0x2a,0x00,0x18,0x28,0xa0,0x04,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x66,0x20,0x8d,
- 0x02,0x10,0x2a,0x00,0x18,0x38,0x00,0x2a,0x14,0x00,0x92,0xe2,0xba,0xff,0xfe,0x4a,0xc4,0x16,0x20,0x8d,
0x02,0x10,0x2a,0x00,0x1c,0x10,0x00,0x02,0x07,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x56,0xcc,
0x02,0x10,0x2a,0x00,0x1f,0x40,0x50,0x01,0x01,0x08,0x5d,0x17,0x77,0x03,0xb0,0xf5,0x41,0x33,0x20,0x8d,
- 0x02,0x10,0x2a,0x00,0x60,0x20,0x15,0xdd,0xee,0x00,0xc8,0xc2,0x2c,0x77,0x17,0x49,0x35,0xdb,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x23,0xc5,0xfe,0x80,0x73,0x01,0xd6,0xae,0x52,0xff,0xfe,0xd5,0x56,0xa5,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x23,0xc6,0x5c,0x91,0x58,0x08,0xc0,0x5a,0x4d,0xff,0xfe,0x65,0x9d,0x69,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x60,0x20,0x1b,0xfa,0xd4,0x00,0x02,0x0c,0x29,0xff,0xfe,0x61,0x4a,0x4c,0x20,0x8d,
0x02,0x10,0x2a,0x00,0x60,0x20,0xb4,0x82,0x92,0x00,0x49,0x1a,0x35,0x8c,0xd8,0xf7,0x01,0xda,0x20,0x8d,
- 0x02,0x10,0x2a,0x00,0x71,0x45,0x00,0xc1,0x00,0x01,0xae,0x29,0x07,0x27,0x2b,0x87,0x0f,0x64,0x14,0x15,
+ 0x02,0x10,0x2a,0x00,0x60,0x20,0xb4,0x89,0x20,0x00,0x50,0x54,0x00,0xff,0xfe,0xfc,0x5e,0xd8,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x7c,0x80,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0x7a,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x7c,0x80,0x00,0x00,0x00,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x20,0x8d,
0x02,0x10,0x2a,0x00,0x8a,0x60,0xe0,0x12,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x20,0x8d,
- 0x02,0x10,0x2a,0x00,0xa0,0x40,0x01,0x00,0x00,0xf3,0x45,0xa5,0x0a,0xc0,0xfe,0xa3,0x71,0xe1,0x20,0x8d,
- 0x02,0x10,0x2a,0x01,0x04,0x88,0x20,0x00,0x98,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0xae,0x40,0x24,0x0e,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0xbb,0xe0,0x00,0xcc,0x00,0x00,0x62,0xa4,0x4c,0xff,0xfe,0x23,0x75,0x10,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x0c,0xa8,0x0a,0x1f,0x30,0x25,0xf9,0x49,0xe4,0x42,0xc9,0x40,0x13,0xe8,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0xd4,0xe0,0x00,0x02,0xd0,0x02,0x44,0x67,0x31,0xe0,0x6f,0xa5,0xb3,0xef,0x20,0x8d,
+ 0x02,0x10,0x2a,0x00,0x0e,0xe2,0x12,0x00,0x19,0x00,0x08,0xd3,0xd2,0xff,0xfe,0xb1,0xbc,0x58,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x02,0x38,0x42,0x0f,0x92,0x00,0xfa,0x5a,0x1a,0x4b,0x1e,0x6a,0xfa,0xdf,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x02,0x38,0x43,0x89,0xc4,0x00,0x3b,0x26,0xd9,0x4e,0x38,0xd5,0x44,0xef,0x20,0x8d,
0x02,0x10,0x2a,0x01,0x04,0x90,0x00,0x16,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x4b,0x00,0x80,0x7c,0x31,0x00,0xcd,0xa1,0x0c,0x6a,0x2b,0xad,0x24,0x18,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf8,0x01,0x41,0x22,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf8,0x01,0x73,0x23,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf8,0x01,0x90,0x91,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf8,0x02,0x00,0x72,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf8,0x02,0x02,0x03,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf8,0x02,0x21,0x44,0xd7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf8,0x02,0x31,0x09,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf9,0x00,0x2a,0x1c,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf9,0x00,0x2b,0x02,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x04,0xf9,0x00,0x4a,0x31,0xde,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
0x02,0x10,0x2a,0x01,0x52,0x00,0x00,0x6c,0x61,0x62,0x7a,0x61,0x74,0x6b,0x6f,0x2e,0x73,0x6b,0x20,0x8d,
- 0x02,0x10,0x2a,0x01,0x63,0x80,0xff,0xfe,0x00,0x73,0x04,0xe3,0xb3,0xcc,0xa8,0x71,0x36,0xd1,0x20,0x8d,
- 0x02,0x10,0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x63,0x80,0xff,0xfe,0x00,0x73,0x10,0xfb,0xd0,0x12,0x85,0x81,0xb4,0xd7,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x07,0xa7,0x00,0x02,0x28,0x04,0xae,0x1f,0x6b,0xff,0xfe,0x9d,0x6c,0x94,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x07,0xc8,0xaa,0xac,0x00,0x89,0x50,0x54,0x00,0xff,0xfe,0xb7,0xf5,0xcb,0x20,0x8d,
0x02,0x10,0x2a,0x01,0x07,0xc8,0xaa,0xc9,0x00,0xc9,0x50,0x54,0x00,0xff,0xfe,0xdf,0xff,0x95,0x20,0x8d,
0x02,0x10,0x2a,0x01,0x07,0xc8,0xd0,0x01,0x01,0xc1,0x50,0x54,0x00,0xff,0xfe,0xee,0x3e,0x1a,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x07,0xc8,0xd0,0x09,0x02,0xaa,0x50,0x54,0x00,0xff,0xfe,0x1b,0xa1,0x96,0x2d,0x00,
+ 0x02,0x10,0x2a,0x01,0x07,0xc8,0xff,0xfa,0x05,0x0e,0xdd,0xfe,0xc9,0x24,0xca,0x0a,0xcb,0xab,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x7e,0x00,0x00,0x00,0x00,0x00,0xf0,0x3c,0x93,0xff,0xfe,0x59,0x66,0xdc,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x7e,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x93,0xff,0xfe,0x3b,0xbb,0x5b,0x20,0x8d,
0x02,0x10,0x2a,0x01,0x87,0x40,0x00,0x01,0xff,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x6a,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x9f,0x40,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x20,0x8d,
0x02,0x10,0x2a,0x01,0xcb,0x00,0x0d,0x3d,0x77,0x00,0x02,0x27,0x0e,0xff,0xfe,0x28,0xc5,0x65,0x20,0x8d,
- 0x02,0x10,0x2a,0x01,0x00,0xd0,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x53,0x20,0x8d,
- 0x02,0x10,0x2a,0x01,0x00,0xd0,0xbe,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x20,0x8d,
- 0x02,0x10,0x2a,0x01,0x0e,0x0a,0x09,0xfb,0xb0,0xe0,0x54,0xf8,0x19,0x01,0x6e,0x83,0x62,0xc1,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x0e,0x0a,0x00,0x20,0x73,0x50,0x91,0x9c,0xb1,0xc3,0x8b,0x83,0xad,0xf9,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x0e,0x0a,0x03,0x01,0x70,0x10,0xb8,0x7d,0xe1,0x4b,0xce,0xa9,0xb9,0x98,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x0e,0x0a,0x04,0x8b,0x2d,0x10,0x94,0xf2,0x4d,0x5c,0xca,0x5f,0xbf,0x49,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x0e,0x0a,0x05,0x30,0xa0,0xa0,0xf4,0x65,0x0a,0xf5,0xbe,0x1b,0x90,0x75,0x20,0x8d,
0x02,0x10,0x2a,0x01,0x0e,0x0a,0x0a,0xa7,0xc8,0xc0,0x96,0x79,0xaf,0xfa,0xb6,0xe5,0xef,0xc7,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x13,0xb8,0xf0,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x01,0x68,0x63,0x28,0x00,0x00,0x02,0xa8,0x2c,0xff,0xfe,0x68,0xe3,0x2c,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x0e,0x11,0x10,0x0c,0x00,0x70,0xcb,0xc8,0x9e,0x31,0x4b,0x77,0x16,0x26,0x20,0x8d,
+ 0x02,0x10,0x2a,0x01,0x0e,0x34,0xee,0x78,0x30,0x60,0x02,0x30,0x48,0xff,0xfe,0x81,0xf1,0xc6,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x12,0x10,0x14,0xa9,0x67,0x00,0x0a,0x00,0x27,0xff,0xfe,0x4e,0x82,0xb6,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x12,0x10,0x46,0x39,0x0f,0x00,0x10,0xa7,0xe9,0x65,0x50,0x9a,0x7a,0x4a,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x12,0x10,0x7c,0x92,0x51,0x00,0x02,0x11,0x32,0xff,0xfe,0xae,0x15,0x2d,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x12,0x10,0x86,0xbf,0xf1,0x00,0x31,0x78,0xd7,0x00,0xd4,0x4d,0x6b,0xb1,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x12,0x10,0x94,0x87,0xa2,0x00,0xed,0xc1,0x93,0xa4,0x09,0x45,0x9a,0x92,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x01,0x68,0x42,0x0b,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x01,0x68,0x63,0x28,0x00,0x00,0x4a,0x21,0x0b,0xff,0xfe,0x26,0x38,0xc3,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x01,0x68,0x67,0x6e,0x00,0x00,0xe6,0x5f,0x01,0xff,0xfe,0x09,0x35,0x91,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x17,0x48,0xf3,0x9f,0x58,0x72,0xde,0xad,0xbe,0xef,0xb1,0xac,0xc0,0xfe,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x01,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x05,0x17,0x10,0xb6,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x21,0x68,0xa3,0x79,0xd1,0x00,0x96,0xde,0x80,0xff,0xfe,0xa3,0xfd,0x00,0x20,0x8d,
0x02,0x10,0x2a,0x02,0x27,0x80,0x90,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x27,0x80,0x90,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x27,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x1a,0x20,0x8d,
0x02,0x10,0x2a,0x02,0x2e,0x02,0x39,0x00,0x54,0x00,0xa0,0x99,0xe1,0xff,0xfe,0xb6,0x0d,0x0e,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x03,0x90,0x90,0x00,0x00,0x00,0xaa,0xa1,0x59,0xff,0xfe,0x43,0xb5,0x7b,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x2f,0x05,0x66,0x0e,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
0x02,0x10,0x2a,0x02,0x00,0x58,0x00,0x97,0x7d,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x6d,0x40,0x30,0x5e,0x06,0x01,0xde,0xa6,0x32,0xff,0xfe,0x44,0x4b,0x25,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x6d,0x40,0x30,0x73,0x0c,0x01,0xde,0xa6,0x32,0xff,0xfe,0x44,0x4b,0x25,0x20,0x8d,
0x02,0x10,0x2a,0x02,0x7a,0x01,0x00,0x00,0x00,0x00,0x00,0x91,0x02,0x28,0x00,0x45,0x01,0x30,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x7a,0xa0,0x16,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xdc,0x8d,0xe0,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x7b,0x40,0x3e,0x4d,0x99,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x7b,0x40,0x59,0x2f,0xa1,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x83,0x88,0xe5,0xc6,0xd3,0x80,0x02,0x01,0x2e,0xff,0xfe,0x82,0xb3,0xcc,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x09,0xa0,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0xa3,0x11,0x81,0x43,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x20,0xa1,
- 0x02,0x10,0x2a,0x02,0x0a,0xf8,0xfa,0xb0,0x08,0x08,0x00,0x85,0x02,0x34,0x01,0x45,0x01,0x32,0x20,0x8d,
- 0x02,0x10,0x2a,0x02,0x0e,0x00,0xff,0xf0,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0xfc,
- 0x02,0x10,0x2a,0x02,0x0e,0x00,0xff,0xf0,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x20,0xfc,
+ 0x02,0x10,0x2a,0x02,0x7b,0x40,0x59,0x28,0x00,0x89,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x7b,0x40,0xc3,0xb5,0xf5,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x83,0x08,0x80,0x87,0xaa,0x00,0x9e,0xa8,0x01,0xb2,0xef,0x98,0x56,0xbf,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0x84,0x2a,0x01,0xdf,0x8a,0x01,0x1e,0x1b,0x0d,0xff,0xfe,0x0b,0x23,0x6d,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xa4,0x4d,0x14,0xd6,0x00,0x01,0x02,0xc0,0x08,0xff,0xfe,0x8f,0xb3,0xb2,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xa4,0x5a,0x94,0xcd,0xf0,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xa4,0x5f,0x3b,0x9d,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xa4,0x67,0x78,0x33,0x00,0x01,0x72,0x85,0xc2,0xff,0xfe,0x2c,0x21,0xe9,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xaa,0x14,0x23,0x80,0xb3,0x00,0x40,0x40,0xbe,0x88,0x8b,0x01,0x0d,0x38,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xc2,0x06,0x20,0x44,0x98,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xc2,0x06,0x20,0x82,0x12,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xc2,0x06,0x30,0x08,0x23,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xc2,0x07,0x00,0x00,0x49,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x14,0xd4,
+ 0x02,0x10,0x2a,0x02,0xc2,0x07,0x20,0x14,0x41,0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xc2,0x07,0x20,0x24,0x61,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xc2,0x07,0x20,0x26,0x66,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x02,0xc2,0x07,0x30,0x02,0x74,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
0x02,0x10,0x2a,0x02,0x0e,0x98,0x00,0x20,0x15,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
- 0x02,0x10,0x2a,0x03,0x40,0x00,0x00,0x47,0x00,0xf1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0x40,0x00,0x00,0x06,0x41,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0x40,0x00,0x00,0x06,0xf8,0x14,0x54,0x8b,0x17,0xff,0xfe,0x31,0xb6,0x4a,0x20,0x8d,
0x02,0x10,0x2a,0x03,0x60,0x00,0x08,0x70,0x00,0x00,0x00,0x46,0x00,0x23,0x00,0x87,0x02,0x18,0x20,0x8d,
- 0x02,0x10,0x2a,0x03,0x73,0x80,0x30,0x15,0x05,0x24,0xaf,0xc5,0xd3,0xbc,0x7c,0x66,0x8f,0x94,0x20,0x8d,
- 0x02,0x10,0x2a,0x03,0x0e,0xc0,0x00,0x00,0x09,0x28,0x8c,0x00,0x93,0xff,0xfe,0x84,0xa0,0x07,0x20,0x8d,
- 0x02,0x10,0x2a,0x03,0x0e,0xc0,0x00,0x00,0x09,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x01,0x20,0x8d,
- 0x02,0x10,0x2a,0x04,0x21,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x20,0x8d,
- 0x02,0x10,0x2a,0x04,0x52,0xc0,0x01,0x01,0x02,0x9e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
- 0x02,0x10,0x2a,0x04,0x52,0xc0,0x01,0x03,0xc4,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0x94,0xe0,0xff,0xff,0x01,0x85,0x02,0x43,0x02,0x18,0x00,0x00,0x00,0x19,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0xb0,0xc0,0x00,0x01,0x00,0xe0,0x00,0x00,0x00,0x00,0x03,0x97,0x60,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xf0,0x00,0x00,0x00,0x00,0x01,0x63,0x30,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0xb0,0xc0,0x00,0x02,0x00,0xf0,0x00,0x00,0x00,0x00,0x01,0x8a,0xd0,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0xb0,0xc0,0x00,0x03,0x00,0xd0,0x00,0x00,0x00,0x00,0x0f,0x3e,0x20,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0xe2,0xc0,0x13,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x03,0x0e,0xc0,0x00,0x00,0x09,0x28,0x00,0x00,0x00,0x00,0x07,0x01,0x07,0x01,0x20,0x8d,
+ 0x02,0x10,0x2a,0x04,0x52,0xc0,0x01,0x03,0xc4,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x20,0x8e,
+ 0x02,0x10,0x2a,0x04,0x52,0xc0,0x30,0x07,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x20,0x8d,
0x02,0x10,0x2a,0x04,0xbc,0x40,0x1d,0xc3,0x00,0x8d,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x01,0x20,0x8d,
0x02,0x10,0x2a,0x05,0x15,0x00,0x07,0x02,0x00,0x00,0x1c,0x00,0x40,0xff,0xfe,0x00,0x00,0x0c,0x20,0x8d,
- 0x02,0x10,0x2a,0x06,0xdd,0x00,0x00,0x10,0x00,0x03,0x02,0x25,0x90,0xff,0xfe,0x32,0x64,0xcc,0x20,0x8d,
- 0x02,0x10,0x2a,0x06,0xdd,0x00,0x00,0x01,0x00,0x22,0x02,0x25,0x90,0xff,0xfe,0x0e,0xbd,0x48,0x20,0x8d,
- 0x02,0x10,0x2a,0x07,0x6b,0x47,0x01,0x00,0x04,0x64,0x00,0x00,0x00,0x00,0x93,0x57,0xff,0xda,0x20,0x8d,
- 0x02,0x10,0x2a,0x07,0xa8,0x80,0x46,0x01,0x10,0x62,0xb4,0xb4,0xbd,0x2a,0x39,0xd4,0x7a,0xcf,0xc8,0xc9,
+ 0x02,0x10,0x2a,0x05,0x35,0x80,0xd1,0x01,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x8d,
+ 0x02,0x10,0x2a,0x05,0x35,0x80,0xdb,0x0b,0x16,0x00,0xc4,0x89,0x76,0xed,0x31,0x3d,0x0b,0x33,0x20,0x8d,
+ 0x02,0x10,0x2a,0x05,0xd0,0x14,0x0a,0x55,0x40,0x01,0x81,0x27,0xaf,0xa7,0xda,0xf9,0xd9,0x1b,0x20,0x8d,
+ 0x02,0x10,0x2a,0x05,0xd0,0x14,0x0a,0x55,0x40,0x01,0xf6,0xab,0xdd,0x5e,0x40,0x39,0xb4,0x6c,0x20,0x8d,
+ 0x02,0x10,0x2a,0x05,0xd0,0x14,0x0a,0x55,0x40,0x03,0x65,0x23,0x50,0xa1,0x01,0x52,0xe8,0x8c,0x20,0x8d,
+ 0x02,0x10,0x2a,0x05,0xd0,0x1a,0x0b,0x7b,0x3c,0x01,0x8b,0xf7,0xae,0x14,0xaf,0xb3,0x33,0xae,0x20,0x8d,
+ 0x02,0x10,0x2a,0x05,0xf4,0x80,0x18,0x00,0x06,0x97,0x54,0x00,0x02,0xff,0xfe,0xb6,0xc3,0x6d,0x20,0x8d,
+ 0x02,0x10,0x2a,0x06,0xe0,0x40,0x76,0x03,0x29,0x18,0xc6,0xef,0x46,0x4e,0x9f,0xe5,0x73,0xec,0x20,0x8d,
0x02,0x10,0x2a,0x07,0xab,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x09,0x46,0x20,0x8d,
- 0x02,0x10,0x2a,0x07,0xab,0xc4,0x00,0x00,0x00,0x00,0x00,0x89,0x02,0x34,0x01,0x80,0x01,0x94,0x20,0x8d,
0x02,0x10,0x2a,0x09,0x26,0x81,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x20,0x8d,
0x02,0x10,0x2a,0x0a,0xc8,0x01,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x83,0x20,0x8d,
- 0x02,0x10,0x2a,0x0b,0xf3,0x00,0x00,0x02,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
- 0x02,0x10,0x2a,0x0c,0x59,0xc0,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x0e,0xe1,0x3a,
+ 0x02,0x10,0x2a,0x0c,0x5a,0x80,0x12,0x10,0xa8,0x00,0x6a,0xf7,0x28,0xff,0xfe,0xe5,0x6b,0x3a,0x20,0x8d,
0x02,0x10,0x2a,0x0d,0x56,0x00,0x00,0x24,0x0a,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0xa9,0x1e,0xd8,0x4d,
- 0x02,0x10,0x2a,0x0d,0xeb,0x00,0x80,0x05,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x20,0x8d,
- 0x02,0x10,0x2a,0x10,0x47,0x40,0x00,0x45,0x00,0x01,0xa0,0x13,0xd1,0xff,0xfe,0x85,0x36,0xe3,0x20,0x8d,
- 0x02,0x10,0x2a,0x10,0x8b,0x40,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x20,0x8f,
+ 0x02,0x10,0x2a,0x0d,0x7c,0x40,0x30,0x00,0x0b,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x0d,0x83,0x40,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x8d,
+ 0x02,0x10,0x2a,0x0f,0xdf,0x00,0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x62,0x20,0x8d,
+ 0x02,0x10,0x2a,0x10,0x37,0x81,0x16,0xb9,0x00,0x01,0xfe,0x3f,0xdb,0xff,0xfe,0x04,0x2d,0x4c,0x20,0x8d,
+ 0x02,0x10,0x2a,0x10,0x37,0x81,0x08,0x4b,0x00,0x01,0xb1,0x23,0x63,0x06,0x94,0x3a,0xf0,0x9b,0x20,0x8d,
+ 0x02,0x10,0x2a,0x10,0xd2,0x00,0x00,0x01,0x00,0x33,0xa6,0xbf,0x01,0xff,0xfe,0x6a,0x46,0xa9,0x20,0x8d,
+ 0x02,0x10,0x2c,0x0f,0xf4,0xc0,0x22,0x02,0x20,0xb0,0x26,0x1c,0x04,0xff,0xfe,0x14,0xda,0xa0,0x20,0x8d,
0x02,0x10,0x2c,0x0f,0xf8,0xf0,0xda,0x51,0x00,0x00,0x70,0xc3,0xee,0xa9,0x97,0x17,0x95,0x79,0x20,0x8d,
- 0x04,0x20,0xd1,0xbb,0x02,0x8d,0x4d,0xd5,0x6a,0x20,0xc0,0xf9,0x16,0x2b,0x84,0x22,0x66,0xe0,0x89,0x45,0x60,0x37,0x52,0xe2,0x0b,0xa5,0xb4,0xf8,0x26,0xb3,0x8f,0x5a,0x30,0xed,0x20,0x8d,
- 0x04,0x20,0xd2,0x59,0x3b,0xd7,0x14,0x7e,0xd0,0x98,0xfe,0x9e,0xa5,0x69,0xf4,0x26,0x6d,0x72,0x6f,0xc3,0x76,0xce,0x1d,0x40,0x41,0xa2,0xa1,0xaf,0xf9,0x6e,0x57,0x2d,0x9d,0xc3,0x20,0x8d,
- 0x04,0x20,0xdf,0xd9,0xed,0x59,0xbf,0x1e,0x77,0x48,0x3c,0x13,0x3b,0xc5,0xc8,0x15,0x86,0x88,0x68,0xf0,0x08,0xe9,0xee,0x9b,0x3d,0xa4,0x33,0x0a,0x68,0x67,0x86,0x9d,0xe2,0x83,0x20,0x8d,
0x04,0x20,0xe9,0xbf,0xa7,0xbd,0x9b,0x54,0x54,0xe8,0xc8,0xae,0x78,0x99,0xa0,0xa3,0xf6,0x5d,0x78,0xe3,0x9e,0x5c,0xa7,0x18,0xb9,0x13,0x0c,0x04,0x9b,0xf3,0x7f,0x27,0x18,0xb0,0x20,0x8d,
- 0x04,0x20,0xf8,0x8d,0x64,0xd2,0xc8,0xe9,0x0f,0x51,0x03,0x1c,0x98,0x33,0x8f,0xe0,0x1e,0xe7,0xb6,0x16,0x8d,0x2a,0xf5,0xf3,0x19,0xce,0xdd,0x9e,0xee,0x17,0xc3,0x8f,0xd6,0xa1,0x20,0x8d,
- 0x04,0x20,0xfb,0xf1,0x17,0xd6,0x03,0x3b,0x01,0x8b,0x98,0xcf,0x16,0x20,0xde,0xaf,0x6c,0xed,0x60,0xab,0x6e,0x14,0x0b,0x58,0x6b,0x2d,0xf8,0x06,0x98,0x37,0x7a,0xff,0x7a,0x0f,0x20,0x8d,
0x04,0x20,0x0f,0xb9,0x71,0x05,0x64,0x83,0x2c,0x68,0x6a,0x9c,0xf0,0x4f,0xc3,0x90,0xcd,0x5c,0x73,0x9a,0xdd,0xb3,0xc6,0x42,0xca,0x09,0xbb,0xcc,0xfe,0x29,0x49,0x9f,0xc7,0x28,0x20,0x8d,
- 0x04,0x20,0x22,0x6e,0x42,0xe4,0xbd,0x2b,0xe5,0x3e,0x30,0xda,0x8a,0x03,0xf3,0x45,0x52,0xac,0x84,0xbf,0xbf,0xc5,0xaa,0x5f,0xe0,0x1b,0x26,0x28,0xb5,0x83,0x2e,0xed,0x4c,0xee,0x20,0x8d,
0x04,0x20,0x2a,0x47,0x8b,0xa0,0x4f,0x67,0x1d,0xcd,0x5d,0x84,0x1a,0xec,0xbd,0xd2,0xaa,0xe9,0x99,0x01,0x96,0x5d,0x4e,0xff,0x64,0x47,0xba,0xde,0xbf,0x56,0x89,0x39,0xac,0xde,0x20,0x8d,
0x04,0x20,0x2b,0xf3,0xe8,0xf5,0xef,0x90,0x14,0xab,0x61,0xe9,0x11,0x97,0x9f,0x18,0x4d,0xb4,0xff,0x89,0x94,0xf7,0x92,0x94,0x53,0xe6,0x9e,0xd4,0xdb,0x85,0x89,0x4d,0x3e,0xc9,0x20,0x8d,
- 0x04,0x20,0x2e,0x4e,0xde,0x51,0xd7,0x28,0x4b,0x29,0x7c,0xff,0x1f,0x8a,0x50,0xb7,0x5e,0xf0,0x81,0xcd,0xe8,0x8a,0x08,0x73,0x58,0x4e,0x43,0x1f,0x7b,0x85,0x9a,0xed,0xe2,0x68,0x20,0x8d,
0x04,0x20,0x35,0xdd,0xd0,0x36,0xa5,0x69,0x4a,0xd2,0xcc,0xb8,0xe9,0x62,0xa3,0x55,0xeb,0x86,0xe2,0xf3,0x03,0x48,0x26,0xe6,0x20,0xad,0xda,0xaa,0xff,0xde,0x16,0xad,0x39,0x9d,0x20,0x8d,
0x04,0x20,0x41,0x47,0x4e,0xc2,0xa1,0x71,0x63,0x3e,0x11,0x54,0x46,0x91,0x80,0xed,0x41,0x16,0x32,0x29,0x19,0x60,0xc9,0xef,0xa3,0xb7,0x96,0x2c,0x94,0xa8,0xdf,0x55,0xd7,0x21,0x20,0x8d,
0x04,0x20,0x44,0xf3,0xb7,0x5e,0x48,0x3c,0xbd,0xa6,0x52,0xaa,0x68,0xb5,0xbf,0xdc,0x01,0x5f,0x4b,0xeb,0x7a,0x25,0xcb,0x4a,0x70,0xbc,0x18,0x8c,0x97,0x5d,0x27,0x54,0x09,0x17,0x20,0x8d,
- 0x04,0x20,0x5c,0x52,0x7f,0x17,0x16,0x4c,0x27,0x36,0x2d,0x05,0xa1,0x19,0x0d,0xbe,0x87,0xab,0x24,0x7b,0xe7,0x38,0x3b,0xa1,0x7f,0xd1,0xd4,0x28,0x16,0x8e,0xfc,0x98,0x7d,0x08,0x20,0x8d,
+ 0x04,0x20,0x53,0xcd,0x56,0x48,0x48,0x8c,0x47,0x07,0x91,0x41,0x82,0x65,0x5b,0x76,0x64,0x03,0x4e,0x09,0xe6,0x6f,0x7e,0x8c,0xbf,0x10,0x84,0xe6,0x54,0xeb,0x56,0xc5,0xbd,0x88,0x20,0x8d,
0x04,0x20,0x67,0xc4,0x17,0xa5,0xcb,0x77,0xbd,0xaa,0x11,0x7f,0x8b,0xc0,0x81,0xf3,0xc0,0x96,0x9d,0x31,0x27,0x9c,0xad,0x6c,0x6d,0x98,0x42,0x70,0xdb,0x50,0x12,0x96,0x0b,0x36,0x20,0x8d,
- 0x04,0x20,0x73,0xdb,0x82,0xe0,0x88,0x40,0x49,0xd8,0x3b,0xa0,0xdd,0x83,0x7c,0x84,0x3c,0xb8,0xd0,0x03,0x0b,0x7a,0x08,0x44,0x4e,0x79,0xd6,0x61,0x23,0x31,0xa9,0xb3,0x07,0x58,0x20,0x8d,
- 0x04,0x20,0x75,0x93,0x21,0xdd,0x99,0x58,0x3c,0x3f,0xae,0x36,0x50,0x58,0x49,0xe2,0xd0,0xc3,0x3a,0x2c,0x4a,0xcf,0x41,0xc4,0x82,0x48,0xab,0xec,0x07,0x5d,0x56,0x2c,0xb4,0x8d,0x20,0x8d,
- 0x04,0x20,0x87,0xd4,0x66,0x0f,0xed,0xf9,0xf5,0xf1,0xcb,0x85,0x37,0xec,0xe1,0x19,0xa8,0xa4,0x03,0xb7,0x13,0x59,0xbb,0xf8,0xd2,0x93,0x92,0x50,0xfa,0x30,0x7a,0xd8,0x43,0xd0,0x20,0x8d,
+ 0x04,0x20,0x65,0x98,0x55,0xd0,0x8a,0xe0,0x29,0xe6,0x5e,0xef,0xb7,0x8b,0x8f,0xc9,0x27,0x53,0x3d,0xd0,0x8c,0xa2,0xfa,0x32,0x2f,0xad,0xf9,0xdc,0xe2,0x4b,0x14,0x66,0x3e,0x23,0x20,0x8d,
0x04,0x20,0x8b,0xfe,0xad,0x19,0xdb,0x97,0x57,0x84,0xec,0xad,0x4f,0xb2,0xdf,0x69,0x53,0x04,0x57,0x19,0x16,0x7a,0x71,0xd7,0x2b,0xab,0x03,0xfd,0x76,0x4d,0xa0,0x70,0xc3,0xe7,0x20,0x8d,
- 0x04,0x20,0x96,0x25,0xde,0x4a,0xbc,0xbd,0x76,0x76,0xee,0x43,0x45,0x76,0xe0,0x0d,0x99,0x83,0xcd,0x83,0x8f,0x94,0xe5,0xde,0x7a,0xf2,0xf0,0x57,0xb8,0x25,0x54,0x17,0xcb,0x3b,0x20,0x8d,
- 0x04,0x20,0x98,0xc6,0x44,0x27,0x90,0x41,0xa6,0x98,0xf9,0x25,0x6c,0x59,0x0f,0x06,0x6d,0x44,0x59,0x0e,0xb2,0x46,0xb0,0xa4,0x37,0x88,0x69,0x8f,0xc1,0x32,0xcd,0x9f,0x15,0xd7,0x20,0x8d,
- 0x04,0x20,0xaa,0x3a,0x16,0x86,0xea,0x59,0x09,0x04,0x78,0xe5,0x10,0x92,0xe1,0x1d,0xad,0xf7,0x56,0x2b,0xac,0xb0,0x97,0x29,0x63,0x30,0xf4,0x1b,0xcf,0xde,0xf3,0x28,0x0a,0x29,0x20,0x8d,
- 0x04,0x20,0xbc,0x27,0xae,0x89,0xc1,0x67,0x73,0x0a,0x08,0x02,0xdf,0xb7,0xcc,0x94,0xc7,0x9f,0xf4,0x72,0x7a,0x9b,0x20,0x0c,0x5c,0x11,0x3d,0x22,0xd6,0x13,0x88,0x66,0x74,0xbf,0x20,0x8d,
+ 0x05,0x20,0xd7,0x7a,0x53,0x89,0xfe,0x02,0x6a,0x59,0xb7,0x0e,0xf8,0x6d,0x9d,0x81,0xbb,0x9f,0x01,0xc0,0xc4,0xee,0x7b,0x36,0x10,0x33,0x07,0xd2,0x29,0xd8,0xec,0xcd,0x8e,0xa3,0x00,0x00,
+ 0x05,0x20,0xd7,0xf1,0x19,0x9e,0x7d,0x0f,0x43,0x97,0x33,0x56,0xe8,0x12,0x1d,0x7d,0xa0,0x4d,0x21,0x5a,0x60,0x73,0xc8,0x7e,0x10,0x55,0x60,0x56,0xbb,0x65,0x50,0xa4,0x17,0x59,0x00,0x00,
+ 0x05,0x20,0xd1,0x17,0xe2,0x34,0x4a,0x61,0x70,0x8b,0x04,0xa2,0xb4,0xb0,0x65,0x59,0x52,0x75,0x67,0x86,0xe6,0x48,0x33,0x31,0x5d,0x87,0x38,0x57,0xd3,0xf8,0x40,0x07,0x73,0xa8,0x00,0x00,
+ 0x05,0x20,0xd9,0x9c,0x20,0xfe,0xc2,0xe6,0x6a,0x16,0x30,0x81,0x54,0xc9,0x3f,0x9a,0x89,0x10,0xa9,0x4b,0xf1,0x05,0x56,0xd5,0x04,0x2d,0xb7,0x6a,0x7b,0x67,0x8d,0xf0,0xbe,0x8f,0x00,0x00,
+ 0x05,0x20,0xdc,0xdb,0x2d,0x39,0xd5,0xe4,0xda,0xb5,0xb6,0x6e,0x98,0x33,0x8f,0x51,0x99,0x54,0x38,0x53,0xa8,0x4e,0xda,0x29,0xd8,0xb5,0x57,0x9d,0x36,0xf0,0x97,0x37,0x18,0x3f,0x00,0x00,
+ 0x05,0x20,0xe1,0x44,0x2d,0x6e,0xd3,0xd9,0xf0,0x95,0x6c,0x52,0x2e,0x44,0x3c,0x27,0x3d,0x78,0xac,0x6e,0x8f,0x27,0x1c,0x0c,0xc0,0x78,0x22,0x3e,0xa1,0x84,0x01,0x42,0x08,0x5c,0x00,0x00,
+ 0x05,0x20,0xe3,0xa5,0x88,0x11,0x4d,0x3d,0xfb,0x02,0xec,0x1f,0xda,0x48,0x86,0x12,0xf6,0x12,0xd9,0x3e,0x68,0x49,0xa7,0xae,0x37,0xfd,0x02,0x48,0x38,0x8b,0xdc,0xd4,0xa6,0x8f,0x00,0x00,
+ 0x05,0x20,0xe5,0x19,0x24,0x71,0xab,0x61,0xb0,0xfe,0x44,0x4a,0x74,0x8d,0xca,0x90,0xc3,0xd6,0x24,0xb4,0xd5,0x03,0xe7,0xf3,0x4f,0xbe,0x12,0x72,0xd6,0xa0,0x4b,0x22,0x0b,0xe1,0x00,0x00,
+ 0x05,0x20,0xee,0xab,0xea,0x3b,0xc2,0x8a,0xe2,0xb3,0xe5,0xe7,0x92,0xf0,0x88,0x05,0x68,0x8d,0x2f,0xe7,0x2c,0xd2,0x00,0x39,0xd4,0x5d,0x07,0xfc,0xa1,0xd6,0xbf,0x89,0xa2,0x40,0x00,0x00,
+ 0x05,0x20,0xf2,0x74,0x4c,0x90,0xc3,0xd9,0x34,0x4d,0x5f,0x6e,0xdb,0xdd,0x7d,0xef,0xa5,0xed,0x6e,0x59,0x9e,0x31,0x41,0x94,0x38,0x84,0xc5,0x08,0xd2,0x23,0xb3,0xa7,0xe0,0x2c,0x00,0x00,
+ 0x05,0x20,0xf3,0x77,0xe5,0xa7,0x11,0xef,0x65,0x91,0x23,0xb8,0x32,0x06,0xcb,0xc0,0x91,0xf7,0x21,0x1d,0x70,0xbc,0x83,0x1b,0x86,0x34,0x35,0x31,0x0f,0x9f,0xc1,0x0d,0xbb,0x56,0x00,0x00,
+ 0x05,0x20,0xfe,0xb0,0x99,0x79,0x95,0x58,0x71,0xb5,0x63,0xcc,0x33,0xeb,0x55,0x91,0x8c,0xb4,0x3a,0xf2,0x8b,0x2d,0x8e,0x47,0xbe,0x25,0x47,0x12,0xcd,0x14,0x48,0xf0,0x1d,0xea,0x00,0x00,
+ 0x05,0x20,0xfc,0x79,0x14,0x77,0x6b,0x0e,0x34,0x8d,0xde,0x01,0x33,0xed,0xb4,0x0e,0xa7,0xc9,0x15,0x4f,0xd0,0x27,0x2c,0xd6,0x5f,0xe9,0x63,0x82,0x8d,0xd5,0x0c,0x9e,0x18,0x29,0x00,0x00,
0x05,0x20,0x07,0x61,0x26,0xd7,0x6c,0x05,0xbf,0xf6,0x2d,0x8c,0xca,0xc4,0x65,0xd3,0xd3,0xb2,0x49,0xe9,0xcc,0x53,0x1e,0xca,0x77,0x84,0xb6,0x10,0x5e,0xc2,0x5a,0xfe,0x28,0xb3,0x00,0x00,
- 0x05,0x20,0x0a,0x26,0x27,0x45,0xb1,0x1e,0xfc,0x27,0x03,0x32,0x0e,0x65,0x9e,0x3c,0x64,0x0e,0x33,0x50,0x3d,0x6c,0x90,0x17,0x0e,0x29,0xee,0x5a,0x58,0xdf,0x08,0xde,0xbf,0x73,0x00,0x00,
+ 0x05,0x20,0x03,0xaa,0x47,0xe9,0xe2,0x77,0xeb,0xa5,0x72,0x27,0x23,0x8b,0x13,0x62,0x61,0x32,0xb5,0xb2,0x1b,0x5a,0x18,0xb2,0xf9,0x26,0x06,0x84,0xee,0x28,0x42,0xac,0xba,0xbc,0x00,0x00,
+ 0x05,0x20,0x08,0xc6,0x19,0x31,0x40,0x96,0xf3,0xe2,0x81,0x4e,0x88,0x54,0x54,0x9e,0xbf,0xfa,0x38,0x7a,0xfa,0x38,0x96,0x13,0x2a,0xc4,0x69,0xa2,0xae,0xe5,0x94,0xc7,0x16,0xb7,0x00,0x00,
+ 0x05,0x20,0x0a,0x26,0x27,0x23,0xdd,0xf3,0x56,0xbe,0x9e,0x9e,0xa7,0xc6,0x3c,0xc5,0x99,0xc4,0x87,0x3b,0x4d,0xb9,0x13,0x62,0x91,0xf2,0x25,0x1c,0x02,0x42,0x63,0xe3,0x63,0x7a,0x00,0x00,
+ 0x05,0x20,0x0c,0x50,0x55,0x46,0x87,0x5a,0x8d,0x14,0xfb,0xa7,0x29,0x70,0x18,0xa6,0x29,0x80,0x8c,0x33,0x42,0x5a,0x8f,0xe4,0x84,0x64,0x3d,0x0e,0xb5,0xbd,0x36,0x34,0x42,0xb6,0x00,0x00,
0x05,0x20,0x17,0x0c,0x56,0xce,0x72,0xa5,0xa0,0xe6,0x23,0x06,0xa3,0xc7,0x08,0x43,0x18,0xee,0x3a,0x46,0x35,0x5d,0x17,0xf6,0x78,0x96,0xa0,0x9c,0x51,0xef,0xbe,0x23,0xfd,0x71,0x00,0x00,
- 0x05,0x20,0x19,0xe7,0x0d,0x3f,0xfe,0x9e,0x0e,0x8e,0x73,0x40,0x40,0xc3,0xba,0x8f,0x41,0xaf,0xf1,0x7b,0xa6,0x83,0x1b,0xc3,0xa4,0xe0,0x6d,0x6c,0x57,0xa7,0x36,0x5d,0x09,0xce,0x00,0x00,
+ 0x05,0x20,0x18,0x31,0xb3,0x9a,0xf8,0x8c,0xec,0x99,0x2e,0x7d,0xe4,0x90,0xa2,0x54,0x27,0xbd,0xe5,0xc8,0x65,0xdf,0x1f,0xaa,0x8f,0xe9,0x0f,0x64,0x85,0x09,0xc3,0x70,0x62,0x13,0x00,0x00,
+ 0x05,0x20,0x1a,0x35,0x98,0x78,0xb1,0xd9,0x48,0x62,0xe9,0x23,0x10,0xfe,0x71,0xdb,0x10,0x5f,0x28,0xc8,0xf3,0xda,0x33,0x9b,0x26,0xcb,0x4d,0xbe,0x7b,0x03,0x76,0xb9,0xe0,0x54,0x00,0x00,
+ 0x05,0x20,0x27,0x7a,0xaf,0x5a,0x9c,0xf4,0x72,0xfe,0x3c,0xdd,0x7a,0xba,0xd7,0x98,0x31,0xde,0x73,0xce,0x84,0x5b,0x41,0xe7,0x9a,0x6a,0xe2,0xc1,0x3b,0x5b,0x37,0x23,0xc7,0xdf,0x00,0x00,
+ 0x05,0x20,0x20,0x90,0xe3,0xd3,0xad,0x87,0xeb,0x2a,0xd9,0x29,0x17,0x74,0x47,0xc9,0x54,0x57,0xfa,0x3d,0x71,0x02,0x11,0xb2,0xc3,0x87,0x31,0xb3,0x9b,0x6f,0x2e,0xfc,0x30,0xea,0x00,0x00,
+ 0x05,0x20,0x22,0x56,0xd6,0x98,0x11,0x61,0xe1,0x5a,0x34,0x9f,0xe2,0x9d,0xf5,0x2b,0xbd,0xbc,0xcc,0x1c,0xf5,0x1d,0x68,0xa5,0xca,0xb1,0xb5,0x4b,0xf1,0xb5,0xff,0x1e,0xdd,0xc0,0x00,0x00,
+ 0x05,0x20,0x37,0x3e,0x28,0x39,0xef,0xa6,0xbc,0xf8,0xf1,0xba,0x11,0x40,0x87,0x42,0xff,0x58,0x46,0x8f,0xb0,0x80,0xfe,0x20,0x75,0xc5,0x43,0xce,0xec,0x9b,0x5d,0x37,0x19,0xf4,0x00,0x00,
0x05,0x20,0x3e,0xe3,0xe0,0xa9,0xbc,0xf4,0x2e,0x59,0xd9,0x20,0xee,0xdf,0x74,0x61,0x4d,0x99,0x0c,0x5c,0x15,0x30,0x9b,0x72,0x16,0x79,0x15,0xf4,0x7a,0xca,0x34,0xcc,0x81,0x99,0x00,0x00,
- 0x05,0x20,0x3b,0x42,0x1c,0x25,0xf7,0xbf,0x79,0xed,0x6d,0x7d,0xef,0x65,0x30,0x7d,0xee,0x16,0x37,0x22,0x72,0x43,0x33,0x28,0x40,0xa3,0xaa,0xf4,0x48,0x49,0x67,0xb1,0x4b,0xfd,0x00,0x00,
+ 0x05,0x20,0x39,0xca,0x8e,0x62,0x0a,0x36,0xa7,0x68,0x22,0xc4,0xcc,0x4a,0xa9,0x16,0x69,0x4b,0x8a,0x1c,0x5f,0x6e,0x4a,0x98,0xb6,0x95,0x82,0xb3,0x66,0x66,0xc5,0x29,0x3a,0xb0,0x00,0x00,
+ 0x05,0x20,0x3b,0xd0,0x80,0xc4,0xab,0x82,0x83,0x11,0x48,0xe5,0x3b,0x23,0x3b,0x17,0x04,0x0f,0xd8,0x39,0x7c,0x1b,0x70,0x73,0x68,0x98,0x11,0x22,0x49,0x51,0x8f,0x20,0x65,0x65,0x00,0x00,
+ 0x05,0x20,0x47,0x1f,0x83,0xc8,0xa3,0x87,0x35,0xcf,0x8e,0x8d,0x22,0xfe,0xf0,0x02,0x63,0x04,0x3a,0x6a,0x49,0x1a,0x3b,0x70,0x17,0xeb,0x05,0xed,0xaf,0x61,0xb6,0x26,0xb8,0x21,0x00,0x00,
+ 0x05,0x20,0x45,0xbd,0x33,0x3d,0x81,0x1e,0x14,0x52,0x88,0x8a,0xa7,0x46,0x0f,0x37,0x25,0xd0,0x59,0x9f,0x78,0xb5,0x7f,0x4a,0xf1,0x54,0x8c,0x2d,0x36,0x32,0xf8,0x10,0xf3,0xcc,0x00,0x00,
+ 0x05,0x20,0x4a,0x8b,0x40,0x25,0xdc,0x06,0x2a,0xed,0x44,0x35,0xec,0x06,0x9e,0x73,0x70,0xf0,0x07,0x06,0x35,0xd1,0x60,0x4f,0x22,0xe8,0xbf,0x8a,0xdf,0xd9,0xeb,0x97,0x73,0x06,0x00,0x00,
0x05,0x20,0x4e,0x77,0x2e,0x12,0x91,0x67,0x6b,0x94,0xc4,0x92,0x2f,0x19,0x67,0x7d,0xcd,0x47,0x02,0xad,0xf8,0x60,0x72,0xed,0x73,0xf1,0x10,0x99,0x2c,0x05,0x61,0x66,0x55,0xd9,0x00,0x00,
- 0x05,0x20,0x53,0x94,0xa6,0x3e,0x14,0x82,0xd4,0xf9,0xd3,0xa7,0x53,0x33,0x05,0xce,0x72,0x64,0xed,0x74,0x09,0x63,0x8f,0x24,0xef,0xda,0x12,0xa1,0x55,0xe0,0xd8,0xbb,0xd3,0x58,0x00,0x00,
+ 0x05,0x20,0x5a,0x29,0xfe,0x8a,0xaa,0x9d,0x78,0x81,0x04,0x53,0x37,0xf5,0x6f,0xb6,0xe1,0x57,0x08,0x80,0xcf,0xf6,0x03,0x11,0x92,0x8d,0x08,0xe3,0x99,0x9f,0x98,0x4a,0x27,0x6b,0x00,0x00,
+ 0x05,0x20,0x5a,0x65,0x0a,0x52,0x9b,0xc7,0x2e,0x92,0x79,0x7b,0xd3,0xf7,0xa4,0x35,0xbe,0x8e,0xb1,0xea,0x2d,0x7e,0x73,0x84,0x6a,0x3f,0xc9,0x9a,0x62,0xe3,0xc6,0x17,0x0e,0x7c,0x00,0x00,
+ 0x05,0x20,0x5c,0x40,0x7f,0x80,0x43,0x91,0x9c,0xfc,0x04,0xdc,0xdc,0x8e,0x01,0xda,0xc8,0xaf,0x90,0x62,0x64,0x16,0xf7,0x11,0xe4,0x87,0xac,0xa4,0x06,0x6f,0x8d,0x87,0x4e,0xd6,0x00,0x00,
+ 0x05,0x20,0x5e,0x69,0x4f,0x31,0x33,0xa7,0xea,0x3e,0xf4,0x7a,0x0a,0x1e,0x74,0x09,0x07,0xa1,0x50,0xf7,0x03,0xf5,0xc6,0x19,0xeb,0x95,0xaa,0x63,0x17,0x10,0x6e,0x68,0xca,0x10,0x00,0x00,
+ 0x05,0x20,0x67,0x82,0xfc,0x36,0xea,0xae,0x95,0x3b,0x5d,0x46,0xf3,0xf4,0x6c,0x50,0x69,0x29,0xc7,0x47,0x87,0xca,0xa6,0x40,0x12,0x40,0x6d,0x12,0x94,0x35,0x17,0x8a,0xba,0x56,0x00,0x00,
+ 0x05,0x20,0x67,0xab,0xce,0xf2,0xe3,0xf3,0xf6,0x19,0xf6,0x56,0xa2,0x4c,0xca,0x91,0x4b,0x93,0xfe,0xbc,0x85,0x50,0x5c,0x20,0x51,0x69,0xfb,0xf0,0x92,0xbb,0x57,0xa3,0x0d,0x05,0x00,0x00,
+ 0x05,0x20,0x62,0xcc,0x44,0x66,0x31,0x76,0x1b,0x43,0xbe,0xe1,0xc9,0x1d,0x20,0x26,0x7d,0xa7,0x06,0x31,0x57,0x0d,0xb9,0x58,0x20,0xb3,0xca,0xb2,0x5e,0x0a,0x15,0x0b,0xba,0x0d,0x00,0x00,
+ 0x05,0x20,0x71,0x68,0x1b,0xc7,0x48,0x8f,0xe9,0xa3,0x53,0x29,0xb6,0x23,0x5a,0x25,0x02,0x45,0x72,0xca,0xa1,0xb6,0x06,0xfc,0xda,0x65,0x71,0x37,0xe6,0xd9,0x30,0x81,0x02,0xfe,0x00,0x00,
+ 0x05,0x20,0x72,0x8b,0x72,0x38,0xfe,0x44,0xe9,0xc2,0xf4,0xbc,0xd8,0xce,0x1c,0xd5,0x50,0xb1,0x63,0x56,0x74,0x5e,0xf2,0xd3,0xe5,0xd5,0x29,0xe4,0x34,0x1d,0xf5,0x1c,0x7a,0xb9,0x00,0x00,
+ 0x05,0x20,0x76,0x74,0x80,0x6c,0xab,0x7b,0x36,0x3a,0x6a,0x78,0xa4,0xa8,0xb8,0xb7,0xe7,0xf9,0x34,0x47,0x6d,0x34,0xca,0xa2,0xc6,0xef,0x81,0xab,0x62,0xb1,0x46,0x86,0xaf,0xd0,0x00,0x00,
+ 0x05,0x20,0x80,0xfc,0x95,0xc8,0x95,0x91,0x2f,0x6b,0x6e,0xc4,0x2b,0xe1,0x2f,0xa0,0xcb,0xb8,0x76,0x5f,0x6f,0x1c,0x27,0xb0,0x3a,0x2c,0xb9,0x8d,0x6c,0x55,0xbd,0x02,0x60,0xe0,0x00,0x00,
+ 0x05,0x20,0x80,0xc6,0x6f,0xb3,0x18,0x5a,0x1a,0xde,0x4e,0xde,0x50,0xd2,0xc6,0x3f,0xc5,0x96,0x09,0x35,0x3a,0x4d,0x88,0x5f,0xa3,0x49,0x37,0xff,0xe6,0xc5,0x43,0x10,0xaf,0xa8,0x00,0x00,
+ 0x05,0x20,0x8a,0x32,0x54,0x37,0x12,0x24,0xb5,0x1d,0xba,0x3c,0x45,0x03,0x2e,0xda,0xfe,0xf1,0x87,0x8f,0x31,0xe5,0xfe,0xed,0xfa,0x38,0x25,0x00,0x99,0xa5,0xf4,0x51,0x02,0xf7,0x00,0x00,
+ 0x05,0x20,0x97,0x4e,0x74,0xcd,0x8b,0x37,0x76,0x15,0x3b,0x6d,0xb5,0xa4,0xa0,0x4b,0xf7,0x34,0x98,0x48,0x67,0x1e,0x99,0xe7,0x24,0xf4,0x00,0xf7,0x06,0x9c,0x45,0x69,0x34,0x01,0x00,0x00,
0x05,0x20,0x91,0x06,0xd1,0x9e,0xbd,0xab,0xc4,0x61,0xb3,0x0a,0xc2,0x3b,0x29,0xf3,0x10,0x38,0xee,0xbd,0x9d,0xe3,0x99,0x97,0x30,0x70,0x6e,0xe6,0xfb,0x6a,0x3c,0x07,0x3d,0xfd,0x00,0x00,
+ 0x05,0x20,0x9c,0x97,0xc1,0xad,0xf4,0xd2,0x07,0xae,0xe8,0x3e,0x14,0x42,0x36,0x85,0x71,0xa0,0xa7,0xef,0x72,0x44,0xf1,0x74,0x8b,0x6f,0xa5,0xa4,0x2c,0x0d,0xcc,0x9f,0xb0,0x9d,0x00,0x00,
+ 0x05,0x20,0x9d,0x0d,0x0f,0x58,0x1a,0x5c,0xb4,0x1a,0xeb,0xef,0x8e,0x91,0x8d,0x8c,0x1b,0x57,0x5d,0x6d,0x97,0x24,0x28,0x45,0x54,0x8a,0x3a,0xd5,0x05,0xfb,0x76,0xac,0x25,0x52,0x00,0x00,
+ 0x05,0x20,0xa4,0xb3,0x30,0x54,0x28,0x0f,0xfb,0xe5,0x76,0xb0,0x31,0xb2,0x65,0x62,0x56,0x72,0x7c,0xc9,0xcd,0x07,0x4d,0x5f,0xb1,0x69,0xe0,0xf7,0x35,0x3d,0x30,0x3c,0x7d,0x64,0x00,0x00,
+ 0x05,0x20,0xa9,0xa9,0xe5,0xae,0x01,0xc2,0x5e,0x76,0x2f,0x5d,0xa3,0x07,0xdc,0xce,0xb8,0xbc,0x6f,0x47,0xaf,0x3a,0x37,0xf8,0x5c,0x86,0xff,0xe9,0xb6,0xa5,0x00,0x93,0x76,0x11,0x00,0x00,
+ 0x05,0x20,0xb2,0x63,0x45,0xf5,0x36,0xb0,0x79,0x58,0x0d,0x8a,0x54,0x52,0x16,0x2f,0x1f,0x74,0x93,0xe0,0x30,0x82,0x1b,0xe4,0x01,0x76,0xf5,0x03,0xa1,0x19,0xa3,0x8d,0x0e,0xce,0x00,0x00,
+ 0x05,0x20,0xb5,0x55,0x31,0x3f,0xe7,0xc7,0x17,0xe4,0x31,0x87,0x47,0x45,0x7c,0x67,0x43,0x5c,0x82,0x73,0xd6,0x62,0x64,0x94,0x92,0x32,0x2d,0x81,0x0e,0x01,0x35,0xc0,0x7e,0xb7,0x00,0x00,
0x05,0x20,0xb5,0x83,0x6f,0xb6,0x11,0xd8,0x0e,0xa8,0x57,0xda,0x15,0x20,0x5b,0x1a,0x6d,0x21,0x15,0x5a,0xbd,0xb4,0x17,0x11,0xc2,0xfb,0x0e,0xfc,0xde,0xe8,0x26,0x56,0xa8,0xac,0x00,0x00,
+ 0x05,0x20,0xba,0xe0,0xd1,0xe5,0x2e,0x27,0x5b,0x1d,0x36,0x57,0x77,0xaf,0x64,0x04,0xfc,0xe1,0x8f,0x8c,0xf1,0x25,0x81,0x2b,0x4f,0x6a,0xf8,0x55,0x48,0xc2,0x5e,0x6f,0x62,0x43,0x00,0x00,
+ 0x05,0x20,0xc0,0xb9,0x7b,0x21,0xbd,0xa2,0x48,0xda,0x8a,0x3e,0xc3,0x6c,0xac,0xfd,0x6d,0x63,0x21,0xb6,0xb3,0x37,0xa9,0x4d,0x42,0x2c,0x9e,0x75,0x61,0x07,0xdc,0xc9,0xab,0x9b,0x00,0x00,
+ 0x05,0x20,0xc8,0xdc,0x00,0xc8,0xdf,0xa1,0xb2,0xe9,0x9f,0x00,0xb3,0x86,0x93,0xc3,0xbc,0x6d,0x56,0xe2,0x83,0xfc,0xf4,0x6e,0x55,0x5d,0xed,0x4e,0x53,0xe6,0xd1,0x4c,0x38,0x3c,0x00,0x00,
0x05,0x20,0xcc,0xaf,0x6c,0x3b,0xd0,0x13,0x76,0x23,0xc3,0x36,0xbb,0x64,0x4a,0x4a,0x06,0x93,0x69,0x6d,0xb0,0x10,0x6e,0x66,0xa4,0x61,0xf8,0x2d,0xe7,0x80,0x72,0x4d,0x53,0x94,0x00,0x00,
+ 0x05,0x20,0xce,0x25,0x15,0xbd,0x08,0xe9,0x67,0x1c,0xa2,0xa5,0x16,0x0e,0x38,0xd9,0xe4,0xc6,0x20,0x31,0x86,0x23,0x21,0x5a,0x5a,0x76,0x1e,0x74,0xd5,0xd3,0x4e,0x86,0x61,0xf4,0x00,0x00,
0x06,0x10,0xfc,0x32,0x17,0xea,0xe4,0x15,0xc3,0xbf,0x98,0x08,0x14,0x9d,0xb5,0xa2,0xc9,0xaa,0x20,0x8d,
0x06,0x10,0xfc,0xc7,0xbe,0x49,0xcc,0xd1,0xdc,0x91,0x31,0x25,0xf0,0xda,0x45,0x7d,0x08,0xce,0x20,0x8d,
};
static const uint8_t chainparams_seed_test[] = {
- 0x04,0x20,0xdf,0x55,0xaa,0x83,0xd5,0xc5,0xb8,0xe7,0x75,0x78,0xd4,0x29,0x51,0x4b,0x26,0x1c,0x23,0xdf,0x28,0x4d,0x29,0x85,0x07,0xb5,0xe2,0x29,0x69,0x3e,0x25,0xbb,0x61,0xcf,0x47,0x9d,
- 0x04,0x20,0x0a,0xdd,0xa2,0x48,0xb5,0x56,0xa3,0x1f,0xca,0x3c,0x4c,0x9e,0xca,0x6e,0xb3,0xd5,0x5e,0x68,0xf6,0x28,0x31,0x57,0x24,0xfb,0x9d,0x2b,0x55,0x4f,0xd7,0x90,0x62,0xd3,0x47,0x9d,
- 0x04,0x20,0x2d,0x04,0xa1,0x4a,0xd4,0x7c,0x7b,0x16,0x2e,0xb7,0xd2,0xa1,0x08,0xc5,0xd2,0xbd,0x53,0x87,0x34,0xdc,0x38,0x26,0xca,0x56,0xf2,0xac,0xc5,0x62,0x70,0x72,0x3f,0x63,0x47,0x9d,
- 0x04,0x20,0x30,0x57,0x85,0xe0,0x02,0x4a,0xd1,0x31,0xeb,0x16,0x1b,0x1d,0xa8,0x43,0x0b,0xb4,0xc6,0xac,0x7d,0x46,0x24,0x0b,0x55,0x9d,0x16,0xe6,0x46,0x03,0x72,0xfe,0xd4,0xef,0x47,0x9d,
- 0x04,0x20,0x36,0x6c,0xf1,0xd2,0xbb,0xda,0xff,0x8c,0x93,0x61,0x10,0xf2,0x9d,0xa1,0xa4,0x0a,0x30,0x9b,0x0c,0x69,0x6d,0xaa,0xd4,0x9c,0xfd,0xb5,0x5b,0x5e,0x30,0x9f,0xf3,0x13,0x47,0x9d,
- 0x04,0x20,0x3e,0xe2,0xf3,0xe5,0xc5,0xbe,0x61,0xdd,0x4c,0x3e,0xdb,0x0d,0xd2,0xf9,0x42,0xe3,0x31,0xb2,0xa8,0x51,0x31,0xf6,0xce,0xc2,0x38,0x20,0x27,0x39,0x73,0x68,0x5a,0x42,0x47,0x9d,
- 0x04,0x20,0x51,0x79,0x05,0x9c,0x8a,0xdf,0x03,0xb5,0x1b,0x17,0xc3,0x86,0xb6,0x54,0xcc,0xe0,0x6e,0x58,0xa6,0x41,0x4c,0xcc,0x0c,0x60,0x08,0xa6,0x0f,0x1d,0x11,0xd8,0x29,0xa6,0x47,0x9d,
+ 0x04,0x20,0xd7,0x13,0xfe,0x00,0xf0,0xf1,0x07,0xcb,0x30,0xb1,0x31,0xc7,0x68,0xbb,0x05,0xca,0x18,0xb5,0x1d,0xb1,0x0f,0xf2,0x7e,0x66,0xdb,0xaa,0xf4,0x05,0xaf,0x37,0x0a,0x62,0x47,0x9d,
+ 0x04,0x20,0xd1,0x71,0xfe,0x4c,0x9e,0xe9,0x99,0xb1,0x6c,0xd5,0xdd,0x3a,0xc3,0xd8,0x74,0x1d,0x42,0x32,0x9f,0xca,0xe9,0x47,0x9e,0x18,0x74,0x43,0x22,0xb9,0xa5,0x31,0xb9,0x66,0x47,0x9d,
+ 0x04,0x20,0xd2,0xe4,0xd1,0x40,0x65,0x5d,0x95,0xaf,0xe8,0x67,0xc0,0xe3,0x72,0xfd,0x0a,0x2e,0x35,0xb7,0xbd,0xac,0x67,0x78,0x36,0xe1,0xb8,0xba,0x30,0xcf,0x2e,0x05,0xdd,0x9d,0x47,0x9d,
+ 0x04,0x20,0xde,0xdd,0xe8,0x01,0x03,0x98,0x3f,0x2d,0x3d,0x8b,0x99,0x27,0xea,0xe1,0xa3,0xde,0xff,0x50,0x30,0xc2,0x41,0x4e,0x7e,0x72,0x24,0x3d,0xad,0x78,0x3c,0xab,0x12,0x67,0x47,0x9d,
+ 0x04,0x20,0xdb,0x9d,0xe0,0xc8,0x5d,0x65,0x4b,0xe0,0x7b,0x0f,0x63,0x80,0x85,0x21,0x73,0x07,0x94,0x0f,0xb0,0x23,0x38,0xec,0x78,0xb6,0x07,0xa1,0xd2,0xb0,0x82,0xf8,0x20,0xea,0x47,0x9d,
+ 0x04,0x20,0xdb,0xc9,0xb2,0xe1,0x4b,0x43,0xf1,0xc9,0x3d,0xea,0x51,0x9a,0x71,0x6b,0x4a,0x15,0xe7,0x3e,0xfe,0x8b,0x24,0x7a,0xaa,0xff,0x53,0xf7,0xfc,0x10,0xc6,0xcc,0x14,0x88,0x47,0x9d,
+ 0x04,0x20,0xe5,0x38,0xc1,0x67,0x52,0x2d,0x6f,0x2f,0xbe,0xc2,0xb3,0x45,0x2b,0x19,0x8c,0x10,0xf3,0x09,0xe5,0x37,0xfe,0x66,0x57,0x6f,0x7a,0x4d,0x78,0xf8,0x50,0x41,0xd6,0x90,0x47,0x9d,
+ 0x04,0x20,0xed,0x76,0x8d,0x28,0xb0,0x44,0x2c,0xff,0xf4,0xd9,0x6a,0x5c,0xf9,0xca,0x5f,0x81,0xa2,0x23,0x48,0x82,0x24,0x2e,0xfc,0xbe,0x0a,0x1e,0xf9,0x02,0x43,0x31,0x37,0xf5,0x47,0x9d,
+ 0x04,0x20,0xee,0x57,0x1b,0xab,0xd0,0xd7,0x27,0xca,0xe7,0xaa,0xe2,0x09,0xf3,0x4e,0x80,0x90,0xd2,0x0a,0x9d,0xc4,0x59,0xd0,0xdc,0xa1,0x97,0x09,0x4e,0x2f,0xfe,0x9f,0xa8,0x0a,0x47,0x9d,
+ 0x04,0x20,0xf7,0xe5,0xb0,0x17,0xdc,0x21,0xed,0xfb,0xb6,0xf5,0xe6,0xb4,0x0b,0xb3,0xf3,0x6c,0xb8,0x3f,0x2a,0x93,0x89,0x66,0x2f,0x05,0x30,0xdf,0xfa,0xdf,0xf2,0x1b,0x52,0x78,0x47,0x9d,
+ 0x04,0x20,0xf0,0x38,0xe6,0xe3,0xbb,0x4d,0x17,0x56,0xd0,0xae,0xf6,0xf4,0xa9,0x99,0x96,0xa9,0xe8,0xfc,0xfb,0x76,0x08,0xed,0x7f,0xb7,0xf0,0xa0,0xd3,0x8d,0xea,0x18,0x87,0x8c,0x47,0x9d,
+ 0x04,0x20,0xf1,0x67,0x83,0x6d,0xa7,0x17,0xa6,0xdd,0x1f,0x19,0x5c,0xbd,0x92,0x8e,0x45,0x0c,0x5c,0x2c,0x9d,0x57,0x98,0xe1,0x46,0x40,0x3d,0x87,0x30,0x02,0x9f,0x1d,0x88,0xde,0x47,0x9d,
+ 0x04,0x20,0xff,0x7b,0xca,0x5b,0xa3,0x4c,0x68,0x7d,0xf1,0x3d,0x18,0xef,0xb4,0x3e,0x39,0x34,0x0d,0x9c,0x3c,0x49,0x9b,0xe7,0x67,0x2c,0x78,0x61,0x42,0x67,0x62,0xd0,0x15,0xb5,0x47,0x9d,
+ 0x04,0x20,0xff,0xbc,0xb7,0x65,0x60,0x0d,0xc1,0x04,0xbc,0x30,0x95,0x67,0xe9,0x37,0x62,0xf7,0x5b,0xe3,0x2a,0xd6,0x3b,0xaf,0x8a,0x98,0xc9,0xfb,0x4b,0x66,0xb2,0xdc,0x13,0xc0,0x47,0x9d,
+ 0x04,0x20,0xf8,0x57,0x5e,0x80,0x2d,0xc4,0xc6,0x5e,0x7f,0x15,0x09,0xee,0xcc,0x29,0xf1,0x65,0x53,0x1c,0x41,0xc1,0xf7,0x51,0xa4,0xb0,0x76,0x86,0xe3,0x10,0x24,0x4d,0xd2,0x11,0x47,0x9d,
+ 0x04,0x20,0xfd,0x74,0x90,0x71,0x06,0xbf,0x2b,0xdc,0x69,0x31,0xf2,0x63,0x1f,0x18,0x17,0x71,0xd2,0x75,0xe4,0xf5,0x35,0x89,0xc0,0x55,0x71,0x05,0xc4,0x77,0x64,0xbf,0x20,0x36,0x47,0x9d,
+ 0x04,0x20,0xfe,0x4c,0x16,0x4f,0x37,0x75,0xb4,0xe2,0x54,0x7d,0x00,0x21,0x39,0x3a,0x2c,0xb7,0xe8,0x9a,0xf3,0x2f,0x8a,0xf6,0xe4,0x6b,0x7d,0xea,0x18,0xc3,0xc3,0x86,0x57,0xc5,0x47,0x9d,
+ 0x04,0x20,0x00,0xe5,0x30,0x05,0x39,0xf9,0x05,0xac,0x6d,0x33,0xe5,0xb4,0x3a,0xd1,0x8c,0x75,0xb3,0x5f,0x9b,0xcc,0xd1,0x76,0xa0,0x24,0x84,0x49,0x4b,0x40,0x67,0xee,0x4d,0x93,0x47,0x9d,
+ 0x04,0x20,0x01,0x25,0x8f,0x4c,0xb4,0x28,0x06,0xaa,0x4f,0xc5,0x5d,0x34,0x19,0x40,0xcd,0xb6,0xb9,0xad,0x52,0x3a,0xc3,0x52,0x05,0x9a,0x97,0x5e,0x69,0x9a,0x2a,0x66,0xde,0x48,0x47,0x9d,
+ 0x04,0x20,0x02,0xee,0xed,0xe8,0x3d,0x20,0xd1,0xb0,0xb7,0x44,0xd6,0xb9,0x08,0x9b,0x13,0x35,0xee,0xf4,0x0b,0x8a,0x6e,0x10,0xfa,0xbc,0x75,0x14,0xcb,0x28,0xd4,0x40,0x44,0x3a,0x47,0x9d,
+ 0x04,0x20,0x03,0x88,0x08,0xcf,0x7c,0xa3,0x1c,0xe6,0xd4,0x7a,0x50,0x61,0x1d,0x84,0x5c,0x95,0x89,0x4f,0x03,0x8c,0x91,0xf4,0x67,0xf2,0x4a,0xc4,0x2a,0x44,0x6e,0x47,0xc8,0xae,0x47,0x9d,
+ 0x04,0x20,0x03,0xe3,0x9a,0xa7,0xe7,0x30,0xa7,0x21,0x93,0x8c,0x52,0x76,0x4b,0x43,0x7d,0x35,0x70,0xa9,0x3d,0x35,0x54,0x11,0x83,0x1b,0xe1,0x7b,0x6d,0xd9,0xaa,0xb2,0x26,0x9b,0x47,0x9d,
+ 0x04,0x20,0x05,0x9e,0xaf,0x67,0x77,0x31,0xef,0xe7,0x65,0xd4,0x3b,0x86,0x2c,0x0c,0x10,0x9c,0x7d,0x4c,0xe4,0x2d,0xb7,0x05,0x12,0x51,0x17,0xfb,0x15,0x47,0xdd,0xd7,0x5b,0x0e,0x47,0x9d,
+ 0x04,0x20,0x06,0x30,0xd8,0x03,0x34,0x16,0x0f,0xa4,0x8f,0xb1,0x21,0xc4,0x53,0x19,0x87,0xa3,0x60,0xf1,0xdb,0x2b,0x09,0xf2,0x18,0x1b,0x1e,0x5a,0x78,0x29,0xe7,0x4e,0x12,0x7e,0x47,0x9d,
+ 0x04,0x20,0x0e,0x90,0xa0,0x77,0x60,0x80,0x95,0x5e,0x1a,0x5f,0xb3,0x1c,0x6d,0x87,0x11,0x20,0x35,0x52,0xe5,0x9d,0x7f,0xf0,0x4d,0xec,0x68,0x30,0xa4,0xca,0xd5,0xaf,0x0e,0x20,0x47,0x9d,
+ 0x04,0x20,0x09,0x3f,0x9b,0xec,0xe7,0xf0,0xd6,0x03,0xba,0x2b,0xac,0xa3,0x13,0x41,0x9c,0x70,0x0e,0x58,0x9a,0x0c,0xd4,0xc3,0x66,0x84,0x7c,0xa7,0x76,0xd9,0xd3,0xa5,0xff,0xba,0x47,0x9d,
+ 0x04,0x20,0x0a,0xe8,0xaf,0x6a,0xc9,0xd7,0x03,0x2a,0x8e,0xc7,0xe7,0xd9,0x47,0x77,0x87,0x3d,0xa4,0x09,0xa8,0xb3,0x44,0x2e,0x4a,0xcf,0xaa,0x08,0x3e,0x79,0x4d,0x2e,0x25,0xfd,0x47,0x9d,
+ 0x04,0x20,0x0d,0x02,0xcf,0x15,0x0e,0x79,0x72,0xab,0xc2,0x25,0xbf,0xab,0x07,0xa1,0xc4,0xe8,0x0e,0xb3,0xe2,0x81,0xcf,0x7e,0xe3,0x4a,0x10,0xc7,0x0e,0x0e,0xbd,0xad,0x32,0x20,0x47,0x9d,
+ 0x04,0x20,0x1e,0xc5,0x90,0x07,0x29,0x4f,0x7e,0xb3,0x46,0x51,0xe9,0x81,0x65,0x24,0x7f,0xae,0xcd,0x96,0xc6,0x00,0xfe,0x70,0x8c,0xc1,0x8a,0xe2,0xe3,0x80,0x48,0x40,0xab,0x10,0x47,0x9d,
+ 0x04,0x20,0x18,0xd3,0xc1,0x52,0xa1,0xde,0xaa,0x4e,0x88,0xf3,0x7f,0x92,0x09,0xcc,0x43,0x6b,0x59,0x76,0x3d,0xce,0x2a,0x66,0x7c,0xa3,0xf3,0x39,0xaf,0x73,0xcf,0xf8,0x83,0x89,0x47,0x9d,
+ 0x04,0x20,0x1c,0x0e,0x75,0xca,0x45,0xb3,0x0f,0xb3,0x7b,0x27,0xb5,0xde,0x22,0x86,0xde,0xe5,0xf3,0xd8,0x95,0x0a,0x11,0x96,0x86,0x84,0xee,0xbd,0x7a,0x04,0xd7,0x90,0xca,0x04,0x47,0x9d,
+ 0x04,0x20,0x1c,0x66,0x71,0x60,0x3c,0xbf,0x22,0x32,0x91,0x56,0xe9,0xbf,0x74,0xb8,0xd7,0x47,0xc1,0x07,0x2e,0x88,0x59,0xa8,0xb0,0x9a,0xd5,0x93,0x09,0xb6,0xdb,0x6e,0x40,0x6a,0x47,0x9d,
+ 0x04,0x20,0x1d,0x83,0xcf,0x89,0x90,0x06,0xa6,0x97,0xb2,0xa9,0x01,0x01,0x1f,0x98,0x62,0x04,0x65,0xa5,0x93,0x3e,0x6a,0x08,0x53,0xa3,0x90,0x2e,0xb5,0x02,0x1e,0x78,0x98,0x3d,0x47,0x9d,
+ 0x04,0x20,0x27,0xe6,0xa8,0x97,0xbc,0x69,0xb7,0x0e,0xd4,0x4d,0xe9,0x9b,0xff,0xe6,0xc9,0xb3,0x3f,0xc5,0xa8,0xa0,0xaf,0x19,0x61,0xd2,0xfb,0x7d,0x5c,0xdf,0x62,0xb0,0x36,0xe6,0x47,0x9d,
+ 0x04,0x20,0x24,0xe9,0x86,0x63,0x9f,0x96,0xe1,0x42,0x3e,0xa3,0x03,0x9d,0xfd,0x23,0xa4,0xeb,0x05,0xfa,0x3a,0xb1,0xcd,0x3a,0xce,0x24,0xbd,0x87,0x99,0x65,0xd9,0x19,0x75,0xf1,0x47,0x9d,
+ 0x04,0x20,0x28,0x50,0xc2,0x49,0xb8,0x3e,0x68,0x10,0xe6,0x02,0xdd,0x01,0x42,0xe5,0x41,0xc1,0x58,0xd5,0x5e,0xb8,0x7b,0xae,0x0a,0x90,0x14,0x0f,0xe3,0x97,0xe4,0xfa,0x2b,0xaf,0x47,0x9d,
+ 0x04,0x20,0x2e,0x43,0x1b,0x30,0xd6,0x62,0x9d,0xf8,0x50,0x8b,0x89,0xcb,0x49,0x2a,0x7b,0x42,0x40,0x10,0x0b,0xfe,0xcd,0xfe,0x6e,0xe8,0x65,0x89,0x2a,0xc3,0x8d,0x49,0xf2,0x2a,0x47,0x9d,
+ 0x04,0x20,0x36,0x3c,0xd4,0x1f,0x8f,0x63,0xfa,0x49,0x62,0xb5,0x69,0xd6,0x9f,0x42,0xaa,0xfe,0x54,0x14,0xd1,0xd2,0xb2,0xae,0x52,0xe1,0x08,0x7e,0xc6,0x15,0x56,0x45,0xbd,0xb3,0x47,0x9d,
+ 0x04,0x20,0x38,0x3d,0xac,0xa2,0x19,0x80,0xdc,0x61,0xff,0xb9,0x37,0xd6,0x53,0xf0,0xb0,0x89,0xb6,0x14,0x33,0x62,0x7c,0x33,0x8a,0x3d,0xdc,0xdd,0xba,0xfb,0x70,0xa4,0x6f,0x9b,0x47,0x9d,
+ 0x04,0x20,0x38,0x04,0x94,0x99,0x3a,0x60,0x61,0x08,0xcc,0xf9,0x43,0x18,0x8f,0x01,0xb5,0x43,0x7e,0x35,0xa5,0x27,0x2a,0xf6,0x85,0x78,0x81,0x36,0xed,0xb6,0xb0,0xd2,0xac,0x77,0x47,0x9d,
+ 0x04,0x20,0x38,0x54,0xfe,0xde,0xcf,0x83,0xb9,0x06,0x7f,0xaa,0x79,0x96,0x58,0x89,0x78,0x45,0x29,0x51,0x9a,0xbf,0x64,0xd1,0x02,0xe2,0x5f,0x74,0x15,0x2e,0x0d,0x8f,0x81,0x9e,0x47,0x9d,
+ 0x04,0x20,0x3c,0x0c,0xec,0x7b,0x47,0x74,0x12,0xcc,0xef,0xe1,0x88,0xcb,0x57,0x11,0xd5,0xd8,0x91,0x7e,0x95,0x17,0x0c,0x12,0xe2,0x46,0x7c,0xc0,0xe3,0xe3,0x92,0x26,0xeb,0x85,0x47,0x9d,
+ 0x04,0x20,0x3d,0x42,0xc6,0x66,0xb0,0x8b,0xcc,0xf9,0x6a,0xfd,0xa7,0x10,0xfe,0x2a,0x45,0xd9,0x3a,0xcd,0x15,0xa4,0x00,0xbf,0xde,0x1a,0x6d,0x3a,0x5b,0xa8,0xc8,0x95,0x6a,0x3c,0x47,0x9d,
+ 0x04,0x20,0x3d,0xb7,0x5c,0xbf,0x7a,0xb7,0x0f,0xe3,0x21,0xeb,0xa1,0x3c,0x8b,0xf3,0x9d,0x72,0x3d,0x69,0xfc,0xcc,0x22,0xa5,0x1c,0xb4,0x3f,0x98,0xcb,0x63,0xa8,0xc8,0x9f,0xcc,0x47,0x9d,
+ 0x04,0x20,0x40,0xc7,0x1f,0x78,0x96,0x51,0xc8,0xd4,0x54,0x0f,0x32,0x00,0xda,0x0d,0x2a,0xb4,0x04,0xff,0x0e,0xf3,0x94,0x8d,0xf4,0x5e,0x23,0x74,0xfa,0x0c,0xfa,0x87,0xfb,0x3b,0x47,0x9d,
+ 0x04,0x20,0x43,0x30,0x0d,0xf9,0x04,0xba,0x10,0x88,0x45,0x56,0xa5,0xee,0x22,0x1d,0xb5,0xe2,0x8d,0xd9,0x1e,0x68,0x8d,0x87,0xaa,0x9b,0x82,0x6a,0x71,0xe5,0x95,0x2b,0x79,0xf6,0x47,0x9d,
+ 0x04,0x20,0x45,0x0e,0x7a,0x38,0x4d,0x97,0xc8,0xd9,0xc7,0x2b,0xbc,0xae,0xa9,0xe3,0x3a,0x40,0x65,0xf3,0xc0,0xc8,0x31,0xab,0xe9,0x02,0x99,0x82,0xb2,0xa0,0x79,0x60,0x92,0xed,0x47,0x9d,
+ 0x04,0x20,0x4a,0x3b,0x66,0x48,0xee,0x55,0x05,0xed,0x91,0x14,0x5e,0x57,0x64,0xeb,0x23,0xab,0x56,0x83,0x56,0x36,0x2d,0x6a,0x2f,0xf8,0x28,0x11,0x37,0x3a,0x73,0x76,0x2e,0x6a,0x47,0x9d,
+ 0x04,0x20,0x4a,0x4b,0x4c,0x27,0xea,0x89,0xb2,0xa6,0x3e,0xf5,0x6e,0xc3,0xa4,0xe8,0xf6,0x5e,0x54,0xcc,0x93,0x64,0xce,0x36,0x82,0xd9,0x5f,0x1b,0x65,0x6b,0x02,0xc6,0x66,0x60,0x47,0x9d,
+ 0x04,0x20,0x4b,0x74,0xfe,0x48,0xc5,0x79,0xd5,0x77,0xba,0xdf,0x52,0x63,0x40,0xc4,0x30,0x04,0xff,0xf5,0x29,0x01,0xcc,0x15,0x5a,0x58,0xf7,0xc0,0x16,0x28,0x83,0x36,0x60,0xa0,0x47,0x9d,
+ 0x04,0x20,0x4c,0x6a,0x4c,0x67,0x94,0x97,0xa4,0xe3,0x78,0x9e,0x16,0x65,0x58,0xf5,0x95,0xa9,0xcd,0x94,0x9a,0xbc,0x40,0xc2,0x4e,0x20,0x71,0x72,0xd9,0x02,0x50,0x75,0x9f,0x41,0x47,0x9d,
+ 0x04,0x20,0x4c,0x85,0xc2,0xc6,0xb5,0x6a,0xf4,0x3d,0x84,0xf9,0xc3,0x8b,0x21,0x7f,0x57,0x7e,0x66,0x66,0x6b,0x6d,0x5f,0x0a,0xd0,0xf0,0x76,0x56,0x65,0x78,0xf8,0xa7,0x42,0x75,0x47,0x9d,
+ 0x04,0x20,0x52,0xf0,0xcb,0x8e,0xa9,0x27,0xd4,0x21,0x57,0x73,0xcb,0x40,0x17,0x6e,0x83,0x73,0xe4,0x59,0xa9,0x89,0x23,0x14,0x14,0x6a,0x91,0x85,0xd2,0xce,0x1c,0x85,0x05,0x06,0x47,0x9d,
+ 0x04,0x20,0x55,0x93,0x75,0x82,0x96,0x4c,0xc8,0x24,0x96,0x48,0xb3,0x9e,0x15,0xf5,0xf5,0x6f,0x5b,0xec,0xf6,0x39,0xff,0xa8,0xaf,0x3a,0x4c,0x5d,0x22,0x3d,0xd3,0x14,0xc3,0x05,0x47,0x9d,
+ 0x04,0x20,0x58,0xbf,0x47,0xe7,0x52,0x8d,0xb5,0x83,0xbc,0x55,0xb1,0xb8,0x02,0xe3,0xdc,0xc2,0xc4,0xe7,0x79,0x85,0xb2,0xe7,0x38,0x27,0xae,0xad,0x0c,0xb8,0x34,0xed,0x71,0xde,0x47,0x9d,
+ 0x04,0x20,0x59,0x76,0xc7,0xdc,0xb8,0x4d,0x1d,0x51,0x40,0x75,0x43,0x57,0xdd,0x3e,0xa3,0x63,0x06,0x0f,0x5e,0x18,0x29,0x10,0x08,0xac,0xa0,0x60,0xd2,0xf3,0x63,0x6e,0xa6,0x58,0x47,0x9d,
0x04,0x20,0x60,0xbe,0xae,0x7d,0xa3,0x4d,0x6a,0x71,0x1a,0x5d,0xe5,0x98,0x9c,0xde,0xa0,0x99,0x39,0x19,0xd3,0x01,0x0a,0x5d,0x1c,0x21,0x43,0x94,0x92,0x71,0x5d,0x77,0xd7,0xdf,0x47,0x9d,
- 0x04,0x20,0x64,0x4e,0x86,0xa1,0x02,0xa1,0x8a,0xef,0xb0,0xd1,0xb5,0x77,0x69,0xb9,0x6a,0xdc,0xdf,0x35,0x8a,0xda,0xa4,0x3e,0x83,0xfa,0x50,0xe6,0xca,0x0e,0x2b,0x99,0x0a,0x17,0x47,0x9d,
- 0x04,0x20,0xa2,0x28,0x3c,0x5a,0x5b,0x82,0x32,0x66,0x11,0xe5,0x71,0xff,0x6b,0x25,0x92,0x75,0xdd,0x7a,0x4f,0x90,0x8b,0x1d,0x34,0xa4,0xf1,0x6e,0xb9,0xfb,0xb5,0x2e,0x7c,0x7f,0x47,0x9d,
- 0x04,0x20,0xc8,0xb5,0x6a,0xba,0x02,0x26,0x45,0x12,0xfb,0x93,0x8a,0x51,0xe4,0xb0,0xf3,0x94,0xb7,0xc0,0x74,0x72,0xeb,0x67,0x91,0x9e,0x04,0x36,0x6a,0x4b,0xef,0x0d,0x88,0xfe,0x47,0x9d,
- 0x04,0x20,0xc8,0xfa,0xcd,0x8c,0xc3,0x6f,0x3c,0xd0,0x27,0x7e,0x7d,0xeb,0x51,0x01,0x65,0xb6,0x9e,0x02,0x09,0x64,0xf4,0x87,0x78,0x7b,0x8f,0x9d,0xaf,0x3b,0xa5,0xcc,0x56,0x2c,0x47,0x9d,
+ 0x04,0x20,0x62,0x42,0x6d,0x98,0xc4,0xa1,0x16,0xc1,0x7d,0x17,0x9e,0x37,0x94,0x88,0x58,0x76,0xa9,0x13,0x6a,0x98,0x39,0x22,0x58,0x13,0xf8,0x9a,0x99,0xa2,0x25,0x56,0x59,0x05,0x47,0x9d,
+ 0x04,0x20,0x6a,0xb1,0x07,0x66,0xbe,0x50,0xec,0x8e,0x6b,0x72,0xfc,0xb4,0xc2,0x67,0x26,0xa1,0x7a,0x10,0x15,0xd3,0xd0,0x36,0x7a,0xf0,0x83,0xd0,0xc3,0x59,0x85,0x68,0x90,0xd8,0x47,0x9d,
+ 0x04,0x20,0x6d,0x6b,0x07,0x72,0xf7,0x45,0x8c,0x1d,0xe3,0x5c,0xf2,0x58,0x20,0xd2,0x95,0x25,0x22,0x51,0xc3,0x59,0x96,0xc1,0xdc,0x7e,0xa4,0x82,0x89,0x0a,0xf5,0x25,0x38,0x1a,0x47,0x9d,
+ 0x04,0x20,0x77,0xaa,0x57,0x56,0x17,0xce,0xdd,0x79,0x64,0xaf,0x78,0xb2,0xf4,0x91,0x36,0x75,0x1c,0x1c,0xcd,0x31,0x35,0x4a,0xe4,0x8b,0x64,0x65,0x4e,0x06,0xec,0x2a,0xc4,0x95,0x47,0x9d,
+ 0x04,0x20,0x70,0x11,0x6d,0x2d,0xa7,0xc9,0x9f,0xd8,0xe3,0xe8,0xae,0x5a,0x4a,0x50,0xac,0x3f,0xd6,0x57,0xad,0xd0,0xa5,0x35,0x14,0xd7,0xb1,0x76,0x58,0xb0,0x90,0xa4,0x1c,0x9b,0x47,0x9d,
+ 0x04,0x20,0x72,0xdb,0xfc,0x04,0x48,0xee,0xec,0xae,0x1b,0xad,0xe6,0x9a,0x87,0xe1,0x17,0xae,0x13,0x70,0xae,0x83,0x90,0x62,0x59,0x30,0xed,0x44,0x43,0xe9,0xab,0xee,0xaa,0xd0,0x47,0x9d,
+ 0x04,0x20,0x74,0xd8,0x56,0x9c,0x5e,0xb4,0x62,0x12,0xea,0x6f,0x1e,0x3d,0x95,0x22,0x50,0x16,0xe3,0xba,0x45,0xb2,0xa3,0xad,0x26,0xb0,0x13,0x74,0xdd,0xec,0x22,0xe0,0x70,0x9a,0x47,0x9d,
+ 0x04,0x20,0x75,0x45,0xe9,0x01,0x21,0x81,0x44,0x1b,0x57,0x76,0x8c,0x3f,0x85,0xa9,0x74,0xf4,0x3c,0xf8,0xd5,0x12,0xcf,0x13,0x1e,0x2f,0x18,0x13,0x78,0xa3,0x51,0x59,0x49,0x49,0x47,0x9d,
+ 0x04,0x20,0x7b,0x3b,0xf1,0xa0,0x78,0xc9,0xba,0xb4,0xd2,0xad,0xed,0x0b,0x1e,0xd2,0x8d,0xd2,0x08,0xd1,0x51,0x5b,0x01,0x74,0x6c,0xc0,0x5d,0xcd,0x4c,0x53,0xf3,0xba,0x16,0xe3,0x47,0x9d,
+ 0x04,0x20,0x7b,0x11,0x26,0x1d,0xf6,0xa1,0xb7,0xc3,0x36,0x19,0x0d,0x27,0x10,0x36,0xb7,0xd5,0x93,0x60,0xc8,0xf8,0x82,0x79,0x46,0xe8,0x78,0xce,0x29,0x50,0x2b,0x44,0x3f,0x7a,0x47,0x9d,
+ 0x04,0x20,0x7b,0x96,0x08,0xa2,0x54,0x5c,0xd0,0x94,0x9c,0x0a,0xa7,0xb3,0xea,0x7d,0x38,0x0b,0x8e,0xee,0x91,0xe3,0x91,0xb9,0xc9,0xcc,0x81,0x28,0x2e,0xc3,0x02,0x9a,0xcf,0x65,0x47,0x9d,
+ 0x04,0x20,0x81,0x34,0x90,0x93,0x9c,0xf9,0xc9,0xe7,0x81,0xa5,0xab,0xf1,0x03,0xe1,0xb3,0x2f,0xf7,0xcf,0x19,0x94,0x2f,0x7a,0x1b,0xc5,0x83,0xc9,0x8c,0xc3,0x5b,0x09,0x96,0x14,0x47,0x9d,
+ 0x04,0x20,0x86,0x7d,0x81,0xf5,0x72,0x30,0xc0,0x91,0x4c,0x8e,0x04,0x48,0x47,0xce,0xcd,0x43,0xef,0x22,0x67,0x17,0xea,0x95,0x2f,0x51,0x4f,0x57,0x67,0x58,0x21,0xa5,0x2e,0x68,0x47,0x9d,
+ 0x04,0x20,0x8b,0xfc,0xf6,0xec,0x3b,0x71,0x25,0x88,0xe8,0xc8,0x72,0xc3,0x89,0x05,0x27,0x81,0x28,0x6b,0xb6,0x72,0xa7,0xc5,0x16,0xaa,0x67,0xe6,0x37,0xb7,0x2b,0x99,0xa8,0x97,0x47,0x9d,
+ 0x04,0x20,0xa2,0x46,0x23,0xd2,0xdb,0x3e,0x7a,0x65,0x05,0xd4,0x45,0x78,0xff,0x3e,0xc1,0x28,0xdb,0xfa,0xf1,0x5e,0x32,0xe9,0x6a,0x8f,0x96,0x45,0x15,0x01,0x7f,0x1f,0x75,0xbf,0x47,0x9d,
+ 0x04,0x20,0xa8,0xa6,0xbb,0x02,0x06,0x65,0x3b,0xb2,0x52,0x79,0xd1,0xc9,0x6a,0x01,0x42,0x43,0xca,0x69,0xe1,0x69,0x90,0xfe,0x2c,0xd2,0x7c,0x18,0xfd,0xab,0xc7,0x71,0x7f,0x8b,0x47,0x9d,
+ 0x04,0x20,0xa9,0x7b,0x48,0xf7,0x73,0xcb,0x07,0x37,0x4e,0xaa,0x68,0xc4,0x67,0x08,0xea,0x5b,0x68,0x0a,0xfe,0x14,0x82,0x6a,0xa1,0x79,0x82,0x9c,0x0b,0x52,0x17,0xd6,0x6b,0x1b,0x47,0x9d,
+ 0x04,0x20,0xb3,0x6e,0x64,0x99,0x26,0x7a,0xeb,0xd4,0x53,0x8c,0x94,0xb1,0x4a,0x37,0x02,0xaa,0xa9,0xc8,0x36,0x11,0xec,0xf9,0x0f,0x08,0xa3,0x9f,0x3e,0xaf,0xd2,0xd1,0x2a,0x0b,0x47,0x9d,
+ 0x04,0x20,0xb3,0xd4,0x15,0x0e,0x3f,0x12,0xed,0xfc,0xab,0x69,0x55,0x91,0x45,0xcf,0xc1,0x2f,0x35,0xa4,0xf7,0x94,0xff,0xd8,0xbe,0x44,0xc8,0x36,0xaf,0x0f,0xa0,0x4e,0x36,0x22,0x47,0x9d,
+ 0x04,0x20,0xb6,0x5e,0x39,0xeb,0x93,0x18,0x22,0xad,0x78,0x94,0x34,0x48,0x31,0x8d,0xd1,0x42,0xb7,0x38,0x58,0x49,0xea,0x00,0xb9,0xcf,0x58,0x43,0x38,0x22,0x22,0x88,0x87,0xde,0x47,0x9d,
+ 0x04,0x20,0xb9,0x80,0xf6,0xa1,0x4a,0x0a,0xc6,0xe3,0x19,0x27,0xe9,0x2d,0x75,0x60,0x14,0x3d,0x2c,0xda,0x97,0x77,0x54,0x9f,0x78,0xb8,0x9b,0x72,0x6a,0x58,0xab,0x8b,0x95,0x95,0x47,0x9d,
+ 0x04,0x20,0xba,0xab,0x91,0x9c,0x48,0x8b,0x9b,0x34,0x5c,0x30,0xf3,0xd2,0x78,0xd3,0xbf,0x09,0x79,0x23,0x4e,0x18,0x5d,0x5e,0x75,0x6b,0xa2,0x91,0x63,0x2c,0x75,0xfd,0x06,0x36,0x47,0x9d,
+ 0x04,0x20,0xbb,0x50,0xf0,0x50,0x8d,0xb7,0x6c,0xd4,0x87,0x59,0x0d,0xfd,0x5f,0x51,0x86,0xa8,0x43,0xb3,0x7a,0xe7,0x2f,0x54,0x97,0x7d,0xed,0xc3,0x7b,0x31,0xe6,0xb9,0x05,0xe7,0x47,0x9d,
+ 0x04,0x20,0xc0,0xc1,0xf5,0x59,0xe8,0x46,0xf6,0x9d,0x41,0xf0,0xde,0x8b,0x32,0xf9,0x6f,0xd6,0xb2,0xd5,0x36,0x56,0x43,0xd3,0x60,0x08,0x55,0x94,0x13,0xf5,0xef,0x7f,0x4d,0x4a,0x47,0x9d,
+ 0x04,0x20,0xce,0xd3,0xd2,0xba,0x56,0xa1,0xde,0xc9,0xc4,0xdb,0x50,0x7b,0xe9,0x4d,0x59,0x65,0x1c,0x02,0x4a,0xa3,0xea,0x73,0xb2,0x66,0x70,0xe7,0x85,0xc1,0x20,0x60,0x79,0x96,0x47,0x9d,
+ 0x04,0x20,0xc8,0x88,0xfe,0x71,0x5f,0xa3,0x6c,0x96,0x6a,0xd7,0x9e,0x38,0x84,0x9f,0x44,0xe1,0x6b,0xdc,0x98,0x31,0xad,0x96,0x29,0xe7,0x00,0x83,0x63,0x03,0xae,0x69,0x2e,0x63,0x47,0x9d,
+ 0x04,0x20,0xcb,0x2a,0x8c,0xe7,0xe5,0x1f,0x4e,0x3a,0x13,0xd6,0x9e,0xd7,0x68,0x51,0x83,0xf4,0x2d,0x3e,0x21,0x38,0x63,0x18,0xe9,0x97,0x27,0xff,0x45,0x48,0xc3,0x6c,0xca,0x59,0x47,0x9d,
+ 0x04,0x20,0xcb,0x80,0x0d,0xdf,0xf0,0xa6,0x28,0x84,0x98,0xc8,0x47,0x72,0xbe,0x53,0x04,0x43,0x9c,0x3a,0x0e,0x46,0x9c,0x75,0x4c,0x57,0x50,0x98,0xe5,0x25,0x80,0x5d,0xa2,0x91,0x47,0x9d,
+ 0x04,0x20,0xcb,0xaa,0x0a,0x5d,0x6e,0x8a,0xfa,0x49,0x5a,0x8c,0x0c,0x9d,0x7a,0xe9,0x9d,0xc6,0xe4,0xcd,0xc1,0x6a,0xff,0xbb,0xf1,0x89,0xf1,0xd5,0x16,0x3f,0xdc,0xbb,0xe9,0x1b,0x47,0x9d,
};
#endif // BITCOIN_CHAINPARAMSSEEDS_H
diff --git a/src/coins.cpp b/src/coins.cpp
index 1abdcb54d2..5983a8a39f 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -99,9 +99,9 @@ void CCoinsViewCache::AddCoin(const COutPoint &outpoint, Coin&& coin, bool possi
TRACE5(utxocache, add,
outpoint.hash.data(),
(uint32_t)outpoint.n,
- (uint32_t)coin.nHeight,
- (int64_t)coin.out.nValue,
- (bool)coin.IsCoinBase());
+ (uint32_t)it->second.coin.nHeight,
+ (int64_t)it->second.coin.out.nValue,
+ (bool)it->second.coin.IsCoinBase());
}
void CCoinsViewCache::EmplaceCoinInternalDANGER(COutPoint&& outpoint, Coin&& coin) {
@@ -296,7 +296,7 @@ bool CCoinsViewErrorCatcher::GetCoin(const COutPoint &outpoint, Coin &coin) cons
try {
return CCoinsViewBacked::GetCoin(outpoint, coin);
} catch(const std::runtime_error& e) {
- for (auto f : m_err_callbacks) {
+ for (const auto& f : m_err_callbacks) {
f();
}
LogPrintf("Error reading from database: %s\n", e.what());
diff --git a/src/coins.h b/src/coins.h
index de297dd427..67fecc9785 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -142,7 +142,6 @@ public:
virtual bool GetKey(COutPoint &key) const = 0;
virtual bool GetValue(Coin &coin) const = 0;
- virtual unsigned int GetValueSize() const = 0;
virtual bool Valid() const = 0;
virtual void Next() = 0;
diff --git a/src/compat.h b/src/compat/compat.h
index 0a44b98b4e..a8e5552c0a 100644
--- a/src/compat.h
+++ b/src/compat/compat.h
@@ -3,21 +3,24 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_COMPAT_H
-#define BITCOIN_COMPAT_H
+#ifndef BITCOIN_COMPAT_COMPAT_H
+#define BITCOIN_COMPAT_COMPAT_H
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h>
#endif
+// Windows defines FD_SETSIZE to 64 (see _fd_types.h in mingw-w64),
+// which is too small for our usage, but allows us to redefine it safely.
+// We redefine it to be 1024, to match glibc, see typesizes.h.
#ifdef WIN32
#ifdef FD_SETSIZE
-#undef FD_SETSIZE // prevent redefinition compiler warning
+#undef FD_SETSIZE
#endif
-#define FD_SETSIZE 1024 // max number of fds in fd_set
+#define FD_SETSIZE 1024
#include <winsock2.h>
#include <ws2tcpip.h>
-#include <stdint.h>
+#include <cstdint>
#else
#include <fcntl.h>
#include <sys/mman.h>
@@ -34,49 +37,54 @@
#include <unistd.h>
#endif
+// We map Linux / BSD error functions and codes, to the equivalent
+// Windows definitions, and use the WSA* names throughout our code.
+// Note that glibc defines EWOULDBLOCK as EAGAIN (see errno.h).
#ifndef WIN32
typedef unsigned int SOCKET;
-#include <errno.h>
+#include <cerrno>
#define WSAGetLastError() errno
#define WSAEINVAL EINVAL
-#define WSAEALREADY EALREADY
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEAGAIN EAGAIN
#define WSAEMSGSIZE EMSGSIZE
#define WSAEINTR EINTR
#define WSAEINPROGRESS EINPROGRESS
#define WSAEADDRINUSE EADDRINUSE
-#define WSAENOTSOCK EBADF
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR -1
#else
-#ifndef WSAEAGAIN
+// WSAEAGAIN doesn't exist on Windows
#ifdef EAGAIN
#define WSAEAGAIN EAGAIN
#else
#define WSAEAGAIN WSAEWOULDBLOCK
#endif
#endif
-#endif
+// Windows doesn't define S_IRUSR or S_IWUSR. We define both
+// here, with the same values as glibc (see stat.h).
#ifdef WIN32
#ifndef S_IRUSR
#define S_IRUSR 0400
#define S_IWUSR 0200
#endif
-#else
+#endif
+
+// Windows defines MAX_PATH as it's maximum path length.
+// We define MAX_PATH for use on non-Windows systems.
+#ifndef WIN32
#define MAX_PATH 1024
#endif
+
+// ssize_t is POSIX, and not present when using MSVC.
#ifdef _MSC_VER
-#if !defined(ssize_t)
-#ifdef _WIN64
-typedef int64_t ssize_t;
-#else
-typedef int32_t ssize_t;
-#endif
-#endif
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
#endif
+// The type of the option value passed to getsockopt & setsockopt
+// differs between Windows and non-Windows.
#ifndef WIN32
typedef void* sockopt_arg_type;
#else
@@ -119,4 +127,4 @@ bool static inline IsSelectableSocket(const SOCKET& s) {
#define MSG_DONTWAIT 0
#endif
-#endif // BITCOIN_COMPAT_H
+#endif // BITCOIN_COMPAT_COMPAT_H
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index 788fa4e55b..b2a31e3ba4 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -26,7 +26,5 @@ static const size_t MIN_SERIALIZABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR *
/** Flags for nSequence and nLockTime locks */
/** Interpret sequence numbers as relative lock-time constraints. */
static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE = (1 << 0);
-/** Use GetMedianTimePast() instead of nTime for end point timestamp. */
-static constexpr unsigned int LOCKTIME_MEDIAN_TIME_PAST = (1 << 1);
#endif // BITCOIN_CONSENSUS_CONSENSUS_H
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 794e0f5383..7c35222713 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -8,6 +8,7 @@
#include <uint256.h>
+#include <chrono>
#include <limits>
#include <map>
@@ -109,6 +110,10 @@ struct Params {
bool fPowNoRetargeting;
int64_t nPowTargetSpacing;
int64_t nPowTargetTimespan;
+ std::chrono::seconds PowTargetSpacing() const
+ {
+ return std::chrono::seconds{nPowTargetSpacing};
+ }
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
/** The best chain should have at least this much work */
uint256 nMinimumChainWork;
diff --git a/src/consensus/validation.h b/src/consensus/validation.h
index 6027bb9aeb..9c0aa09356 100644
--- a/src/consensus/validation.h
+++ b/src/consensus/validation.h
@@ -79,6 +79,7 @@ enum class BlockValidationResult {
BLOCK_INVALID_PREV, //!< A block this one builds on is invalid
BLOCK_TIME_FUTURE, //!< block timestamp was > 2 hours in the future (or our clock is bad)
BLOCK_CHECKPOINT, //!< the block failed to meet one of our checkpoints
+ BLOCK_HEADER_LOW_WORK //!< the block header may be on a too-little-work chain
};
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 77c516427a..ec21a2f7f4 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -265,7 +265,7 @@ int ParseSighashString(const UniValue& sighash)
{std::string("SINGLE"), int(SIGHASH_SINGLE)},
{std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)},
};
- std::string strHashType = sighash.get_str();
+ const std::string& strHashType = sighash.get_str();
const auto& it = map_sighash_values.find(strHashType);
if (it != map_sighash_values.end()) {
hash_type = it->second;
diff --git a/src/crc32c/CMakeLists.txt b/src/crc32c/CMakeLists.txt
index 71692d5796..2f52db104c 100644
--- a/src/crc32c/CMakeLists.txt
+++ b/src/crc32c/CMakeLists.txt
@@ -296,9 +296,10 @@ target_include_directories(crc32c
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
-target_compile_definitions(crc32c
-PRIVATE
- CRC32C_HAVE_CONFIG_H=1
+set_property(
+ TARGET crc32c_arm64 crc32c_sse42 crc32c
+ APPEND
+ PROPERTY COMPILE_DEFINITIONS CRC32C_HAVE_CONFIG_H
)
set_target_properties(crc32c
diff --git a/src/crypto/muhash.cpp b/src/crypto/muhash.cpp
index 57ed357645..7d14b7938e 100644
--- a/src/crypto/muhash.cpp
+++ b/src/crypto/muhash.cpp
@@ -298,7 +298,7 @@ void Num3072::ToBytes(unsigned char (&out)[BYTE_SIZE]) {
Num3072 MuHash3072::ToNum3072(Span<const unsigned char> in) {
unsigned char tmp[Num3072::BYTE_SIZE];
- uint256 hashed_in = (CHashWriter(SER_DISK, 0) << in).GetSHA256();
+ uint256 hashed_in{(HashWriter{} << in).GetSHA256()};
ChaCha20(hashed_in.data(), hashed_in.size()).Keystream(tmp, Num3072::BYTE_SIZE);
Num3072 out{tmp};
@@ -318,7 +318,7 @@ void MuHash3072::Finalize(uint256& out) noexcept
unsigned char data[Num3072::BYTE_SIZE];
m_numerator.ToBytes(data);
- out = (CHashWriter(SER_DISK, 0) << data).GetSHA256();
+ out = (HashWriter{} << data).GetSHA256();
}
MuHash3072& MuHash3072::operator*=(const MuHash3072& mul) noexcept
diff --git a/src/cuckoocache.h b/src/cuckoocache.h
index d0dc61c7e6..61f553806e 100644
--- a/src/cuckoocache.h
+++ b/src/cuckoocache.h
@@ -12,7 +12,9 @@
#include <atomic>
#include <cmath>
#include <cstring>
+#include <limits>
#include <memory>
+#include <optional>
#include <utility>
#include <vector>
@@ -326,7 +328,7 @@ public:
}
/** setup initializes the container to store no more than new_size
- * elements.
+ * elements and no less than 2 elements.
*
* setup should only be called once.
*
@@ -336,8 +338,8 @@ public:
uint32_t setup(uint32_t new_size)
{
// depth_limit must be at least one otherwise errors can occur.
- depth_limit = static_cast<uint8_t>(std::log2(static_cast<float>(std::max((uint32_t)2, new_size))));
size = std::max<uint32_t>(2, new_size);
+ depth_limit = static_cast<uint8_t>(std::log2(static_cast<float>(size)));
table.resize(size);
collection_flags.setup(size);
epoch_flags.resize(size);
@@ -357,12 +359,21 @@ public:
*
* @param bytes the approximate number of bytes to use for this data
* structure
- * @returns the maximum number of elements storable (see setup()
- * documentation for more detail)
+ * @returns A pair of the maximum number of elements storable (see setup()
+ * documentation for more detail) and the approxmiate total size of these
+ * elements in bytes or std::nullopt if the size requested is too large.
*/
- uint32_t setup_bytes(size_t bytes)
+ std::optional<std::pair<uint32_t, size_t>> setup_bytes(size_t bytes)
{
- return setup(bytes/sizeof(Element));
+ size_t requested_num_elems = bytes / sizeof(Element);
+ if (std::numeric_limits<uint32_t>::max() < requested_num_elems) {
+ return std::nullopt;
+ }
+
+ auto num_elems = setup(bytes/sizeof(Element));
+
+ size_t approx_size_bytes = num_elems * sizeof(Element);
+ return std::make_pair(num_elems, approx_size_bytes);
}
/** insert loops at most depth_limit times trying to insert a hash
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
index a2f1f32780..4dbc839941 100644
--- a/src/dbwrapper.cpp
+++ b/src/dbwrapper.cpp
@@ -4,15 +4,28 @@
#include <dbwrapper.h>
-#include <memory>
+#include <fs.h>
+#include <logging.h>
#include <random.h>
+#include <tinyformat.h>
+#include <util/strencodings.h>
+#include <util/system.h>
+#include <algorithm>
+#include <cassert>
+#include <cstdarg>
+#include <cstdint>
+#include <cstdio>
#include <leveldb/cache.h>
+#include <leveldb/db.h>
#include <leveldb/env.h>
#include <leveldb/filter_policy.h>
-#include <memenv.h>
-#include <stdint.h>
-#include <algorithm>
+#include <leveldb/helpers/memenv/memenv.h>
+#include <leveldb/iterator.h>
+#include <leveldb/options.h>
+#include <leveldb/status.h>
+#include <memory>
+#include <optional>
class CBitcoinLevelDBLogger : public leveldb::Logger {
public:
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index 1109cb5888..665eaa0e98 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -7,14 +7,26 @@
#include <clientversion.h>
#include <fs.h>
+#include <logging.h>
#include <serialize.h>
#include <span.h>
#include <streams.h>
-#include <util/strencodings.h>
-#include <util/system.h>
+#include <cstddef>
+#include <cstdint>
+#include <exception>
#include <leveldb/db.h>
+#include <leveldb/iterator.h>
+#include <leveldb/options.h>
+#include <leveldb/slice.h>
+#include <leveldb/status.h>
#include <leveldb/write_batch.h>
+#include <stdexcept>
+#include <string>
+#include <vector>
+namespace leveldb {
+class Env;
+}
static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
@@ -166,11 +178,6 @@ public:
}
return true;
}
-
- unsigned int GetValueSize() {
- return piter->value().size();
- }
-
};
class CDBWrapper
@@ -318,22 +325,6 @@ public:
pdb->GetApproximateSizes(&range, 1, &size);
return size;
}
-
- /**
- * Compact a certain range of keys in the database.
- */
- template<typename K>
- void CompactRange(const K& key_begin, const K& key_end) const
- {
- CDataStream ssKey1(SER_DISK, CLIENT_VERSION), ssKey2(SER_DISK, CLIENT_VERSION);
- ssKey1.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
- ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
- ssKey1 << key_begin;
- ssKey2 << key_end;
- leveldb::Slice slKey1((const char*)ssKey1.data(), ssKey1.size());
- leveldb::Slice slKey2((const char*)ssKey2.data(), ssKey2.size());
- pdb->CompactRange(&slKey1, &slKey2);
- }
};
#endif // BITCOIN_DBWRAPPER_H
diff --git a/src/external_signer.cpp b/src/external_signer.cpp
index d125fe479b..094314e878 100644
--- a/src/external_signer.cpp
+++ b/src/external_signer.cpp
@@ -28,7 +28,7 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
if (!result.isArray()) {
throw std::runtime_error(strprintf("'%s' received invalid response, expected array of signers", command));
}
- for (UniValue signer : result.getValues()) {
+ for (const UniValue& signer : result.getValues()) {
// Check for error
const UniValue& error = find_value(signer, "error");
if (!error.isNull()) {
@@ -49,7 +49,7 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
if (signer.m_fingerprint.compare(fingerprintStr) == 0) duplicate = true;
}
if (duplicate) break;
- std::string name = "";
+ std::string name;
const UniValue& model_field = find_value(signer, "model");
if (model_field.isStr() && model_field.getValStr() != "") {
name += model_field.getValStr();
diff --git a/src/fs.cpp b/src/fs.cpp
index 74b167e313..07cce269ed 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -126,7 +126,7 @@ bool FileLock::TryLock()
if (hFile == INVALID_HANDLE_VALUE) {
return false;
}
- _OVERLAPPED overlapped = {0};
+ _OVERLAPPED overlapped = {};
if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, std::numeric_limits<DWORD>::max(), std::numeric_limits<DWORD>::max(), &overlapped)) {
reason = GetErrorReason();
return false;
diff --git a/src/fs.h b/src/fs.h
index cc55793b95..ac58c4a2ba 100644
--- a/src/fs.h
+++ b/src/fs.h
@@ -9,6 +9,7 @@
#include <cstdio>
#include <filesystem>
+#include <functional>
#include <iomanip>
#include <ios>
#include <ostream>
@@ -68,7 +69,11 @@ public:
static inline path u8path(const std::string& utf8_str)
{
+#if __cplusplus < 202002L
return std::filesystem::u8path(utf8_str);
+#else
+ return std::filesystem::path(std::u8string{utf8_str.begin(), utf8_str.end()});
+#endif
}
// Disallow implicit std::string conversion for absolute to avoid
@@ -199,6 +204,7 @@ bool create_directories(const std::filesystem::path& p, std::error_code& ec) = d
/** Bridge operations to C stdio */
namespace fsbridge {
+ using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
FILE *fopen(const fs::path& p, const char *mode);
/**
diff --git a/src/hash.cpp b/src/hash.cpp
index f58b29e3ba..06caaac6ee 100644
--- a/src/hash.cpp
+++ b/src/hash.cpp
@@ -16,7 +16,7 @@ inline uint32_t ROTL32(uint32_t x, int8_t r)
unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vDataToHash)
{
- // The following is MurmurHash3 (x86_32), see https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
+ // The following is MurmurHash3 (x86_32), see https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp
uint32_t h1 = nHashSeed;
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
@@ -86,9 +86,9 @@ uint256 SHA256Uint256(const uint256& input)
return result;
}
-CHashWriter TaggedHash(const std::string& tag)
+HashWriter TaggedHash(const std::string& tag)
{
- CHashWriter writer(SER_GETHASH, 0);
+ HashWriter writer{};
uint256 taghash;
CSHA256().Write((const unsigned char*)tag.data(), tag.size()).Finalize(taghash.begin());
writer << taghash << taghash;
diff --git a/src/hash.h b/src/hash.h
index 0ccef2105f..b1ff3acc7d 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -96,20 +96,12 @@ inline uint160 Hash160(const T1& in1)
}
/** A writer stream (for serialization) that computes a 256-bit hash. */
-class CHashWriter
+class HashWriter
{
private:
CSHA256 ctx;
- const int nType;
- const int nVersion;
public:
-
- CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
-
- int GetType() const { return nType; }
- int GetVersion() const { return nVersion; }
-
void write(Span<const std::byte> src)
{
ctx.Write(UCharCast(src.data()), src.size());
@@ -144,6 +136,26 @@ public:
return ReadLE64(result.begin());
}
+ template <typename T>
+ HashWriter& operator<<(const T& obj)
+ {
+ ::Serialize(*this, obj);
+ return *this;
+ }
+};
+
+class CHashWriter : public HashWriter
+{
+private:
+ const int nType;
+ const int nVersion;
+
+public:
+ CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {}
+
+ int GetType() const { return nType; }
+ int GetVersion() const { return nVersion; }
+
template<typename T>
CHashWriter& operator<<(const T& obj) {
// Serialize to this stream
@@ -203,12 +215,12 @@ unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vData
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
-/** Return a CHashWriter primed for tagged hashes (as specified in BIP 340).
+/** Return a HashWriter primed for tagged hashes (as specified in BIP 340).
*
* The returned object will have SHA256(tag) written to it twice (= 64 bytes).
* A tagged hash can be computed by feeding the message into this object, and
- * then calling CHashWriter::GetSHA256().
+ * then calling HashWriter::GetSHA256().
*/
-CHashWriter TaggedHash(const std::string& tag);
+HashWriter TaggedHash(const std::string& tag);
#endif // BITCOIN_HASH_H
diff --git a/src/headerssync.cpp b/src/headerssync.cpp
new file mode 100644
index 0000000000..757b942cd9
--- /dev/null
+++ b/src/headerssync.cpp
@@ -0,0 +1,317 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <headerssync.h>
+#include <logging.h>
+#include <pow.h>
+#include <timedata.h>
+#include <util/check.h>
+
+// The two constants below are computed using the simulation script on
+// https://gist.github.com/sipa/016ae445c132cdf65a2791534dfb7ae1
+
+//! Store a commitment to a header every HEADER_COMMITMENT_PERIOD blocks.
+constexpr size_t HEADER_COMMITMENT_PERIOD{584};
+
+//! Only feed headers to validation once this many headers on top have been
+//! received and validated against commitments.
+constexpr size_t REDOWNLOAD_BUFFER_SIZE{13959}; // 13959/584 = ~23.9 commitments
+
+// Our memory analysis assumes 48 bytes for a CompressedHeader (so we should
+// re-calculate parameters if we compress further)
+static_assert(sizeof(CompressedHeader) == 48);
+
+HeadersSyncState::HeadersSyncState(NodeId id, const Consensus::Params& consensus_params,
+ const CBlockIndex* chain_start, const arith_uint256& minimum_required_work) :
+ m_id(id), m_consensus_params(consensus_params),
+ m_chain_start(chain_start),
+ m_minimum_required_work(minimum_required_work),
+ m_current_chain_work(chain_start->nChainWork),
+ m_commit_offset(GetRand<unsigned>(HEADER_COMMITMENT_PERIOD)),
+ m_last_header_received(m_chain_start->GetBlockHeader()),
+ m_current_height(chain_start->nHeight)
+{
+ // Estimate the number of blocks that could possibly exist on the peer's
+ // chain *right now* using 6 blocks/second (fastest blockrate given the MTP
+ // rule) times the number of seconds from the last allowed block until
+ // today. This serves as a memory bound on how many commitments we might
+ // store from this peer, and we can safely give up syncing if the peer
+ // exceeds this bound, because it's not possible for a consensus-valid
+ // chain to be longer than this (at the current time -- in the future we
+ // could try again, if necessary, to sync a longer chain).
+ m_max_commitments = 6*(Ticks<std::chrono::seconds>(GetAdjustedTime() - NodeSeconds{std::chrono::seconds{chain_start->GetMedianTimePast()}}) + MAX_FUTURE_BLOCK_TIME) / HEADER_COMMITMENT_PERIOD;
+
+ LogPrint(BCLog::NET, "Initial headers sync started with peer=%d: height=%i, max_commitments=%i, min_work=%s\n", m_id, m_current_height, m_max_commitments, m_minimum_required_work.ToString());
+}
+
+/** Free any memory in use, and mark this object as no longer usable. This is
+ * required to guarantee that we won't reuse this object with the same
+ * SaltedTxidHasher for another sync. */
+void HeadersSyncState::Finalize()
+{
+ Assume(m_download_state != State::FINAL);
+ m_header_commitments = {};
+ m_last_header_received.SetNull();
+ m_redownloaded_headers = {};
+ m_redownload_buffer_last_hash.SetNull();
+ m_redownload_buffer_first_prev_hash.SetNull();
+ m_process_all_remaining_headers = false;
+ m_current_height = 0;
+
+ m_download_state = State::FINAL;
+}
+
+/** Process the next batch of headers received from our peer.
+ * Validate and store commitments, and compare total chainwork to our target to
+ * see if we can switch to REDOWNLOAD mode. */
+HeadersSyncState::ProcessingResult HeadersSyncState::ProcessNextHeaders(const
+ std::vector<CBlockHeader>& received_headers, const bool full_headers_message)
+{
+ ProcessingResult ret;
+
+ Assume(!received_headers.empty());
+ if (received_headers.empty()) return ret;
+
+ Assume(m_download_state != State::FINAL);
+ if (m_download_state == State::FINAL) return ret;
+
+ if (m_download_state == State::PRESYNC) {
+ // During PRESYNC, we minimally validate block headers and
+ // occasionally add commitments to them, until we reach our work
+ // threshold (at which point m_download_state is updated to REDOWNLOAD).
+ ret.success = ValidateAndStoreHeadersCommitments(received_headers);
+ if (ret.success) {
+ if (full_headers_message || m_download_state == State::REDOWNLOAD) {
+ // A full headers message means the peer may have more to give us;
+ // also if we just switched to REDOWNLOAD then we need to re-request
+ // headers from the beginning.
+ ret.request_more = true;
+ } else {
+ Assume(m_download_state == State::PRESYNC);
+ // If we're in PRESYNC and we get a non-full headers
+ // message, then the peer's chain has ended and definitely doesn't
+ // have enough work, so we can stop our sync.
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: incomplete headers message at height=%i (presync phase)\n", m_id, m_current_height);
+ }
+ }
+ } else if (m_download_state == State::REDOWNLOAD) {
+ // During REDOWNLOAD, we compare our stored commitments to what we
+ // receive, and add headers to our redownload buffer. When the buffer
+ // gets big enough (meaning that we've checked enough commitments),
+ // we'll return a batch of headers to the caller for processing.
+ ret.success = true;
+ for (const auto& hdr : received_headers) {
+ if (!ValidateAndStoreRedownloadedHeader(hdr)) {
+ // Something went wrong -- the peer gave us an unexpected chain.
+ // We could consider looking at the reason for failure and
+ // punishing the peer, but for now just give up on sync.
+ ret.success = false;
+ break;
+ }
+ }
+
+ if (ret.success) {
+ // Return any headers that are ready for acceptance.
+ ret.pow_validated_headers = PopHeadersReadyForAcceptance();
+
+ // If we hit our target blockhash, then all remaining headers will be
+ // returned and we can clear any leftover internal state.
+ if (m_redownloaded_headers.empty() && m_process_all_remaining_headers) {
+ LogPrint(BCLog::NET, "Initial headers sync complete with peer=%d: releasing all at height=%i (redownload phase)\n", m_id, m_redownload_buffer_last_height);
+ } else if (full_headers_message) {
+ // If the headers message is full, we need to request more.
+ ret.request_more = true;
+ } else {
+ // For some reason our peer gave us a high-work chain, but is now
+ // declining to serve us that full chain again. Give up.
+ // Note that there's no more processing to be done with these
+ // headers, so we can still return success.
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: incomplete headers message at height=%i (redownload phase)\n", m_id, m_redownload_buffer_last_height);
+ }
+ }
+ }
+
+ if (!(ret.success && ret.request_more)) Finalize();
+ return ret;
+}
+
+bool HeadersSyncState::ValidateAndStoreHeadersCommitments(const std::vector<CBlockHeader>& headers)
+{
+ // The caller should not give us an empty set of headers.
+ Assume(headers.size() > 0);
+ if (headers.size() == 0) return true;
+
+ Assume(m_download_state == State::PRESYNC);
+ if (m_download_state != State::PRESYNC) return false;
+
+ if (headers[0].hashPrevBlock != m_last_header_received.GetHash()) {
+ // Somehow our peer gave us a header that doesn't connect.
+ // This might be benign -- perhaps our peer reorged away from the chain
+ // they were on. Give up on this sync for now (likely we will start a
+ // new sync with a new starting point).
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: non-continuous headers at height=%i (presync phase)\n", m_id, m_current_height);
+ return false;
+ }
+
+ // If it does connect, (minimally) validate and occasionally store
+ // commitments.
+ for (const auto& hdr : headers) {
+ if (!ValidateAndProcessSingleHeader(hdr)) {
+ return false;
+ }
+ }
+
+ if (m_current_chain_work >= m_minimum_required_work) {
+ m_redownloaded_headers.clear();
+ m_redownload_buffer_last_height = m_chain_start->nHeight;
+ m_redownload_buffer_first_prev_hash = m_chain_start->GetBlockHash();
+ m_redownload_buffer_last_hash = m_chain_start->GetBlockHash();
+ m_redownload_chain_work = m_chain_start->nChainWork;
+ m_download_state = State::REDOWNLOAD;
+ LogPrint(BCLog::NET, "Initial headers sync transition with peer=%d: reached sufficient work at height=%i, redownloading from height=%i\n", m_id, m_current_height, m_redownload_buffer_last_height);
+ }
+ return true;
+}
+
+bool HeadersSyncState::ValidateAndProcessSingleHeader(const CBlockHeader& current)
+{
+ Assume(m_download_state == State::PRESYNC);
+ if (m_download_state != State::PRESYNC) return false;
+
+ int next_height = m_current_height + 1;
+
+ // Verify that the difficulty isn't growing too fast; an adversary with
+ // limited hashing capability has a greater chance of producing a high
+ // work chain if they compress the work into as few blocks as possible,
+ // so don't let anyone give a chain that would violate the difficulty
+ // adjustment maximum.
+ if (!PermittedDifficultyTransition(m_consensus_params, next_height,
+ m_last_header_received.nBits, current.nBits)) {
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: invalid difficulty transition at height=%i (presync phase)\n", m_id, next_height);
+ return false;
+ }
+
+ if (next_height % HEADER_COMMITMENT_PERIOD == m_commit_offset) {
+ // Add a commitment.
+ m_header_commitments.push_back(m_hasher(current.GetHash()) & 1);
+ if (m_header_commitments.size() > m_max_commitments) {
+ // The peer's chain is too long; give up.
+ // It's possible the chain grew since we started the sync; so
+ // potentially we could succeed in syncing the peer's chain if we
+ // try again later.
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: exceeded max commitments at height=%i (presync phase)\n", m_id, next_height);
+ return false;
+ }
+ }
+
+ m_current_chain_work += GetBlockProof(CBlockIndex(current));
+ m_last_header_received = current;
+ m_current_height = next_height;
+
+ return true;
+}
+
+bool HeadersSyncState::ValidateAndStoreRedownloadedHeader(const CBlockHeader& header)
+{
+ Assume(m_download_state == State::REDOWNLOAD);
+ if (m_download_state != State::REDOWNLOAD) return false;
+
+ int64_t next_height = m_redownload_buffer_last_height + 1;
+
+ // Ensure that we're working on a header that connects to the chain we're
+ // downloading.
+ if (header.hashPrevBlock != m_redownload_buffer_last_hash) {
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: non-continuous headers at height=%i (redownload phase)\n", m_id, next_height);
+ return false;
+ }
+
+ // Check that the difficulty adjustments are within our tolerance:
+ uint32_t previous_nBits{0};
+ if (!m_redownloaded_headers.empty()) {
+ previous_nBits = m_redownloaded_headers.back().nBits;
+ } else {
+ previous_nBits = m_chain_start->nBits;
+ }
+
+ if (!PermittedDifficultyTransition(m_consensus_params, next_height,
+ previous_nBits, header.nBits)) {
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: invalid difficulty transition at height=%i (redownload phase)\n", m_id, next_height);
+ return false;
+ }
+
+ // Track work on the redownloaded chain
+ m_redownload_chain_work += GetBlockProof(CBlockIndex(header));
+
+ if (m_redownload_chain_work >= m_minimum_required_work) {
+ m_process_all_remaining_headers = true;
+ }
+
+ // If we're at a header for which we previously stored a commitment, verify
+ // it is correct. Failure will result in aborting download.
+ // Also, don't check commitments once we've gotten to our target blockhash;
+ // it's possible our peer has extended its chain between our first sync and
+ // our second, and we don't want to return failure after we've seen our
+ // target blockhash just because we ran out of commitments.
+ if (!m_process_all_remaining_headers && next_height % HEADER_COMMITMENT_PERIOD == m_commit_offset) {
+ if (m_header_commitments.size() == 0) {
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: commitment overrun at height=%i (redownload phase)\n", m_id, next_height);
+ // Somehow our peer managed to feed us a different chain and
+ // we've run out of commitments.
+ return false;
+ }
+ bool commitment = m_hasher(header.GetHash()) & 1;
+ bool expected_commitment = m_header_commitments.front();
+ m_header_commitments.pop_front();
+ if (commitment != expected_commitment) {
+ LogPrint(BCLog::NET, "Initial headers sync aborted with peer=%d: commitment mismatch at height=%i (redownload phase)\n", m_id, next_height);
+ return false;
+ }
+ }
+
+ // Store this header for later processing.
+ m_redownloaded_headers.push_back(header);
+ m_redownload_buffer_last_height = next_height;
+ m_redownload_buffer_last_hash = header.GetHash();
+
+ return true;
+}
+
+std::vector<CBlockHeader> HeadersSyncState::PopHeadersReadyForAcceptance()
+{
+ std::vector<CBlockHeader> ret;
+
+ Assume(m_download_state == State::REDOWNLOAD);
+ if (m_download_state != State::REDOWNLOAD) return ret;
+
+ while (m_redownloaded_headers.size() > REDOWNLOAD_BUFFER_SIZE ||
+ (m_redownloaded_headers.size() > 0 && m_process_all_remaining_headers)) {
+ ret.emplace_back(m_redownloaded_headers.front().GetFullHeader(m_redownload_buffer_first_prev_hash));
+ m_redownloaded_headers.pop_front();
+ m_redownload_buffer_first_prev_hash = ret.back().GetHash();
+ }
+ return ret;
+}
+
+CBlockLocator HeadersSyncState::NextHeadersRequestLocator() const
+{
+ Assume(m_download_state != State::FINAL);
+ if (m_download_state == State::FINAL) return {};
+
+ auto chain_start_locator = LocatorEntries(m_chain_start);
+ std::vector<uint256> locator;
+
+ if (m_download_state == State::PRESYNC) {
+ // During pre-synchronization, we continue from the last header received.
+ locator.push_back(m_last_header_received.GetHash());
+ }
+
+ if (m_download_state == State::REDOWNLOAD) {
+ // During redownload, we will download from the last received header that we stored.
+ locator.push_back(m_redownload_buffer_last_hash);
+ }
+
+ locator.insert(locator.end(), chain_start_locator.begin(), chain_start_locator.end());
+
+ return CBlockLocator{std::move(locator)};
+}
diff --git a/src/headerssync.h b/src/headerssync.h
new file mode 100644
index 0000000000..16da964246
--- /dev/null
+++ b/src/headerssync.h
@@ -0,0 +1,277 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_HEADERSSYNC_H
+#define BITCOIN_HEADERSSYNC_H
+
+#include <arith_uint256.h>
+#include <chain.h>
+#include <consensus/params.h>
+#include <net.h> // For NodeId
+#include <primitives/block.h>
+#include <uint256.h>
+#include <util/bitdeque.h>
+#include <util/hasher.h>
+
+#include <deque>
+#include <vector>
+
+// A compressed CBlockHeader, which leaves out the prevhash
+struct CompressedHeader {
+ // header
+ int32_t nVersion{0};
+ uint256 hashMerkleRoot;
+ uint32_t nTime{0};
+ uint32_t nBits{0};
+ uint32_t nNonce{0};
+
+ CompressedHeader()
+ {
+ hashMerkleRoot.SetNull();
+ }
+
+ CompressedHeader(const CBlockHeader& header)
+ {
+ nVersion = header.nVersion;
+ hashMerkleRoot = header.hashMerkleRoot;
+ nTime = header.nTime;
+ nBits = header.nBits;
+ nNonce = header.nNonce;
+ }
+
+ CBlockHeader GetFullHeader(const uint256& hash_prev_block) {
+ CBlockHeader ret;
+ ret.nVersion = nVersion;
+ ret.hashPrevBlock = hash_prev_block;
+ ret.hashMerkleRoot = hashMerkleRoot;
+ ret.nTime = nTime;
+ ret.nBits = nBits;
+ ret.nNonce = nNonce;
+ return ret;
+ };
+};
+
+/** HeadersSyncState:
+ *
+ * We wish to download a peer's headers chain in a DoS-resistant way.
+ *
+ * The Bitcoin protocol does not offer an easy way to determine the work on a
+ * peer's chain. Currently, we can query a peer's headers by using a GETHEADERS
+ * message, and our peer can return a set of up to 2000 headers that connect to
+ * something we know. If a peer's chain has more than 2000 blocks, then we need
+ * a way to verify that the chain actually has enough work on it to be useful to
+ * us -- by being above our anti-DoS minimum-chain-work threshold -- before we
+ * commit to storing those headers in memory. Otherwise, it would be cheap for
+ * an attacker to waste all our memory by serving us low-work headers
+ * (particularly for a new node coming online for the first time).
+ *
+ * To prevent memory-DoS with low-work headers, while still always being
+ * able to reorg to whatever the most-work chain is, we require that a chain
+ * meet a work threshold before committing it to memory. We can do this by
+ * downloading a peer's headers twice, whenever we are not sure that the chain
+ * has sufficient work:
+ *
+ * - In the first download phase, called pre-synchronization, we can calculate
+ * the work on the chain as we go (just by checking the nBits value on each
+ * header, and validating the proof-of-work).
+ *
+ * - Once we have reached a header where the cumulative chain work is
+ * sufficient, we switch to downloading the headers a second time, this time
+ * processing them fully, and possibly storing them in memory.
+ *
+ * To prevent an attacker from using (eg) the honest chain to convince us that
+ * they have a high-work chain, but then feeding us an alternate set of
+ * low-difficulty headers in the second phase, we store commitments to the
+ * chain we see in the first download phase that we check in the second phase,
+ * as follows:
+ *
+ * - In phase 1 (presync), store 1 bit (using a salted hash function) for every
+ * N headers that we see. With a reasonable choice of N, this uses relatively
+ * little memory even for a very long chain.
+ *
+ * - In phase 2 (redownload), keep a lookahead buffer and only accept headers
+ * from that buffer into the block index (permanent memory usage) once they
+ * have some target number of verified commitments on top of them. With this
+ * parametrization, we can achieve a given security target for potential
+ * permanent memory usage, while choosing N to minimize memory use during the
+ * sync (temporary, per-peer storage).
+ */
+
+class HeadersSyncState {
+public:
+ ~HeadersSyncState() {}
+
+ enum class State {
+ /** PRESYNC means the peer has not yet demonstrated their chain has
+ * sufficient work and we're only building commitments to the chain they
+ * serve us. */
+ PRESYNC,
+ /** REDOWNLOAD means the peer has given us a high-enough-work chain,
+ * and now we're redownloading the headers we saw before and trying to
+ * accept them */
+ REDOWNLOAD,
+ /** We're done syncing with this peer and can discard any remaining state */
+ FINAL
+ };
+
+ /** Return the current state of our download */
+ State GetState() const { return m_download_state; }
+
+ /** Return the height reached during the PRESYNC phase */
+ int64_t GetPresyncHeight() const { return m_current_height; }
+
+ /** Return the block timestamp of the last header received during the PRESYNC phase. */
+ uint32_t GetPresyncTime() const { return m_last_header_received.nTime; }
+
+ /** Return the amount of work in the chain received during the PRESYNC phase. */
+ arith_uint256 GetPresyncWork() const { return m_current_chain_work; }
+
+ /** Construct a HeadersSyncState object representing a headers sync via this
+ * download-twice mechanism).
+ *
+ * id: node id (for logging)
+ * consensus_params: parameters needed for difficulty adjustment validation
+ * chain_start: best known fork point that the peer's headers branch from
+ * minimum_required_work: amount of chain work required to accept the chain
+ */
+ HeadersSyncState(NodeId id, const Consensus::Params& consensus_params,
+ const CBlockIndex* chain_start, const arith_uint256& minimum_required_work);
+
+ /** Result data structure for ProcessNextHeaders. */
+ struct ProcessingResult {
+ std::vector<CBlockHeader> pow_validated_headers;
+ bool success{false};
+ bool request_more{false};
+ };
+
+ /** Process a batch of headers, once a sync via this mechanism has started
+ *
+ * received_headers: headers that were received over the network for processing.
+ * Assumes the caller has already verified the headers
+ * are continuous, and has checked that each header
+ * satisfies the proof-of-work target included in the
+ * header (but not necessarily verified that the
+ * proof-of-work target is correct and passes consensus
+ * rules).
+ * full_headers_message: true if the message was at max capacity,
+ * indicating more headers may be available
+ * ProcessingResult.pow_validated_headers: will be filled in with any
+ * headers that the caller can fully process and
+ * validate now (because these returned headers are
+ * on a chain with sufficient work)
+ * ProcessingResult.success: set to false if an error is detected and the sync is
+ * aborted; true otherwise.
+ * ProcessingResult.request_more: if true, the caller is suggested to call
+ * NextHeadersRequestLocator and send a getheaders message using it.
+ */
+ ProcessingResult ProcessNextHeaders(const std::vector<CBlockHeader>&
+ received_headers, bool full_headers_message);
+
+ /** Issue the next GETHEADERS message to our peer.
+ *
+ * This will return a locator appropriate for the current sync object, to continue the
+ * synchronization phase it is in.
+ */
+ CBlockLocator NextHeadersRequestLocator() const;
+
+private:
+ /** Clear out all download state that might be in progress (freeing any used
+ * memory), and mark this object as no longer usable.
+ */
+ void Finalize();
+
+ /**
+ * Only called in PRESYNC.
+ * Validate the work on the headers we received from the network, and
+ * store commitments for later. Update overall state with successfully
+ * processed headers.
+ * On failure, this invokes Finalize() and returns false.
+ */
+ bool ValidateAndStoreHeadersCommitments(const std::vector<CBlockHeader>& headers);
+
+ /** In PRESYNC, process and update state for a single header */
+ bool ValidateAndProcessSingleHeader(const CBlockHeader& current);
+
+ /** In REDOWNLOAD, check a header's commitment (if applicable) and add to
+ * buffer for later processing */
+ bool ValidateAndStoreRedownloadedHeader(const CBlockHeader& header);
+
+ /** Return a set of headers that satisfy our proof-of-work threshold */
+ std::vector<CBlockHeader> PopHeadersReadyForAcceptance();
+
+private:
+ /** NodeId of the peer (used for log messages) **/
+ const NodeId m_id;
+
+ /** We use the consensus params in our anti-DoS calculations */
+ const Consensus::Params& m_consensus_params;
+
+ /** Store the last block in our block index that the peer's chain builds from */
+ const CBlockIndex* m_chain_start{nullptr};
+
+ /** Minimum work that we're looking for on this chain. */
+ const arith_uint256 m_minimum_required_work;
+
+ /** Work that we've seen so far on the peer's chain */
+ arith_uint256 m_current_chain_work;
+
+ /** m_hasher is a salted hasher for making our 1-bit commitments to headers we've seen. */
+ const SaltedTxidHasher m_hasher;
+
+ /** A queue of commitment bits, created during the 1st phase, and verified during the 2nd. */
+ bitdeque<> m_header_commitments;
+
+ /** The (secret) offset on the heights for which to create commitments.
+ *
+ * m_header_commitments entries are created at any height h for which
+ * (h % HEADER_COMMITMENT_PERIOD) == m_commit_offset. */
+ const unsigned m_commit_offset;
+
+ /** m_max_commitments is a bound we calculate on how long an honest peer's chain could be,
+ * given the MTP rule.
+ *
+ * Any peer giving us more headers than this will have its sync aborted. This serves as a
+ * memory bound on m_header_commitments. */
+ uint64_t m_max_commitments{0};
+
+ /** Store the latest header received while in PRESYNC (initialized to m_chain_start) */
+ CBlockHeader m_last_header_received;
+
+ /** Height of m_last_header_received */
+ int64_t m_current_height{0};
+
+ /** During phase 2 (REDOWNLOAD), we buffer redownloaded headers in memory
+ * until enough commitments have been verified; those are stored in
+ * m_redownloaded_headers */
+ std::deque<CompressedHeader> m_redownloaded_headers;
+
+ /** Height of last header in m_redownloaded_headers */
+ int64_t m_redownload_buffer_last_height{0};
+
+ /** Hash of last header in m_redownloaded_headers (initialized to
+ * m_chain_start). We have to cache it because we don't have hashPrevBlock
+ * available in a CompressedHeader.
+ */
+ uint256 m_redownload_buffer_last_hash;
+
+ /** The hashPrevBlock entry for the first header in m_redownloaded_headers
+ * We need this to reconstruct the full header when it's time for
+ * processing.
+ */
+ uint256 m_redownload_buffer_first_prev_hash;
+
+ /** The accumulated work on the redownloaded chain. */
+ arith_uint256 m_redownload_chain_work;
+
+ /** Set this to true once we encounter the target blockheader during phase
+ * 2 (REDOWNLOAD). At this point, we can process and store all remaining
+ * headers still in m_redownloaded_headers.
+ */
+ bool m_process_all_remaining_headers{false};
+
+ /** Current state of our headers sync. */
+ State m_download_state{State::PRESYNC};
+};
+
+#endif // BITCOIN_HEADERSSYNC_H
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index b8f69b038c..e68436cc2c 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -9,7 +9,7 @@
#include <httpserver.h>
#include <chainparamsbase.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <netbase.h>
#include <node/interface_ui.h>
#include <rpc/protocol.h> // For HTTP status codes
@@ -142,7 +142,8 @@ static std::vector<CSubNet> rpc_allow_subnets;
//! Work queue for handling longer requests off the event loop thread
static std::unique_ptr<WorkQueue<HTTPClosure>> g_work_queue{nullptr};
//! Handlers for (sub)paths
-static std::vector<HTTPPathHandler> pathHandlers;
+static GlobalMutex g_httppathhandlers_mutex;
+static std::vector<HTTPPathHandler> pathHandlers GUARDED_BY(g_httppathhandlers_mutex);
//! Bound listening sockets
static std::vector<evhttp_bound_socket *> boundSockets;
@@ -243,6 +244,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
// Find registered handler for prefix
std::string strURI = hreq->GetURI();
std::string path;
+ LOCK(g_httppathhandlers_mutex);
std::vector<HTTPPathHandler>::const_iterator i = pathHandlers.begin();
std::vector<HTTPPathHandler>::const_iterator iend = pathHandlers.end();
for (; i != iend; ++i) {
@@ -674,11 +676,13 @@ std::optional<std::string> GetQueryParameterFromUri(const char* uri, const std::
void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler)
{
LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch);
+ LOCK(g_httppathhandlers_mutex);
pathHandlers.push_back(HTTPPathHandler(prefix, exactMatch, handler));
}
void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch)
{
+ LOCK(g_httppathhandlers_mutex);
std::vector<HTTPPathHandler>::iterator i = pathHandlers.begin();
std::vector<HTTPPathHandler>::iterator iend = pathHandlers.end();
for (; i != iend; ++i)
diff --git a/src/i2p.cpp b/src/i2p.cpp
index caff8c1e69..28be8009dc 100644
--- a/src/i2p.cpp
+++ b/src/i2p.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <compat/endian.h>
#include <crypto/sha256.h>
#include <fs.h>
@@ -12,11 +12,11 @@
#include <netaddress.h>
#include <netbase.h>
#include <random.h>
-#include <util/strencodings.h>
#include <tinyformat.h>
#include <util/readwritefile.h>
#include <util/sock.h>
#include <util/spanparsing.h>
+#include <util/strencodings.h>
#include <util/system.h>
#include <chrono>
@@ -115,8 +115,19 @@ namespace sam {
Session::Session(const fs::path& private_key_file,
const CService& control_host,
CThreadInterrupt* interrupt)
- : m_private_key_file(private_key_file), m_control_host(control_host), m_interrupt(interrupt),
- m_control_sock(std::make_unique<Sock>(INVALID_SOCKET))
+ : m_private_key_file{private_key_file},
+ m_control_host{control_host},
+ m_interrupt{interrupt},
+ m_control_sock{std::make_unique<Sock>(INVALID_SOCKET)},
+ m_transient{false}
+{
+}
+
+Session::Session(const CService& control_host, CThreadInterrupt* interrupt)
+ : m_control_host{control_host},
+ m_interrupt{interrupt},
+ m_control_sock{std::make_unique<Sock>(INVALID_SOCKET)},
+ m_transient{true}
{
}
@@ -314,6 +325,7 @@ void Session::DestGenerate(const Sock& sock)
// https://geti2p.net/spec/common-structures#key-certificates
// "7" or "EdDSA_SHA512_Ed25519" - "Recent Router Identities and Destinations".
// Use "7" because i2pd <2.24.0 does not recognize the textual form.
+ // If SIGNATURE_TYPE is not specified, then the default one is DSA_SHA1.
const Reply& reply = SendRequestAndGetReply(sock, "DEST GENERATE SIGNATURE_TYPE=7", false);
m_private_key = DecodeI2PBase64(reply.Get("PRIV"));
@@ -355,29 +367,47 @@ void Session::CreateIfNotCreatedAlready()
return;
}
- Log("Creating SAM session with %s", m_control_host.ToString());
+ const auto session_type = m_transient ? "transient" : "persistent";
+ const auto session_id = GetRandHash().GetHex().substr(0, 10); // full is overkill, too verbose in the logs
+
+ Log("Creating %s SAM session %s with %s", session_type, session_id, m_control_host.ToString());
auto sock = Hello();
- const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file);
- if (read_ok) {
- m_private_key.assign(data.begin(), data.end());
+ if (m_transient) {
+ // The destination (private key) is generated upon session creation and returned
+ // in the reply in DESTINATION=.
+ const Reply& reply = SendRequestAndGetReply(
+ *sock,
+ strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=TRANSIENT SIGNATURE_TYPE=7", session_id));
+
+ m_private_key = DecodeI2PBase64(reply.Get("DESTINATION"));
} else {
- GenerateAndSavePrivateKey(*sock);
- }
+ // Read our persistent destination (private key) from disk or generate
+ // one and save it to disk. Then use it when creating the session.
+ const auto& [read_ok, data] = ReadBinaryFile(m_private_key_file);
+ if (read_ok) {
+ m_private_key.assign(data.begin(), data.end());
+ } else {
+ GenerateAndSavePrivateKey(*sock);
+ }
- const std::string& session_id = GetRandHash().GetHex().substr(0, 10); // full is an overkill, too verbose in the logs
- const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));
+ const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));
- SendRequestAndGetReply(*sock, strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
- session_id, private_key_b64));
+ SendRequestAndGetReply(*sock,
+ strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
+ session_id,
+ private_key_b64));
+ }
m_my_addr = CService(DestBinToAddr(MyDestination()), I2P_SAM31_PORT);
m_session_id = session_id;
m_control_sock = std::move(sock);
- LogPrintfCategory(BCLog::I2P, "SAM session created: session id=%s, my address=%s\n",
- m_session_id, m_my_addr.ToString());
+ Log("%s SAM session %s created, my address=%s",
+ Capitalize(session_type),
+ m_session_id,
+ m_my_addr.ToString());
}
std::unique_ptr<Sock> Session::StreamAccept()
@@ -405,12 +435,12 @@ void Session::Disconnect()
{
if (m_control_sock->Get() != INVALID_SOCKET) {
if (m_session_id.empty()) {
- Log("Destroying incomplete session");
+ Log("Destroying incomplete SAM session");
} else {
- Log("Destroying session %s", m_session_id);
+ Log("Destroying SAM session %s", m_session_id);
}
}
- m_control_sock->Reset();
+ m_control_sock = std::make_unique<Sock>(INVALID_SOCKET);
m_session_id.clear();
}
} // namespace sam
diff --git a/src/i2p.h b/src/i2p.h
index 433fcc3a08..ebbcb437da 100644
--- a/src/i2p.h
+++ b/src/i2p.h
@@ -5,7 +5,7 @@
#ifndef BITCOIN_I2P_H
#define BITCOIN_I2P_H
-#include <compat.h>
+#include <compat/compat.h>
#include <fs.h>
#include <netaddress.h>
#include <sync.h>
@@ -71,6 +71,19 @@ public:
CThreadInterrupt* interrupt);
/**
+ * Construct a transient session which will generate its own I2P private key
+ * rather than read the one from disk (it will not be saved on disk either and
+ * will be lost once this object is destroyed). This will not initiate any IO,
+ * the session will be lazily created later when first used.
+ * @param[in] control_host Location of the SAM proxy.
+ * @param[in,out] interrupt If this is signaled then all operations are canceled as soon as
+ * possible and executing methods throw an exception. Notice: only a pointer to the
+ * `CThreadInterrupt` object is saved, so it must not be destroyed earlier than this
+ * `Session` object.
+ */
+ Session(const CService& control_host, CThreadInterrupt* interrupt);
+
+ /**
* Destroy the session, closing the internally used sockets. The sockets that have been
* returned by `Accept()` or `Connect()` will not be closed, but they will be closed by
* the SAM proxy because the session is destroyed. So they will return an error next time
@@ -262,6 +275,12 @@ private:
* SAM session id.
*/
std::string m_session_id GUARDED_BY(m_mutex);
+
+ /**
+ * Whether this is a transient session (the I2P private key will not be
+ * read or written to disk).
+ */
+ const bool m_transient;
};
} // namespace sam
diff --git a/src/index/base.cpp b/src/index/base.cpp
index 323547900d..3eea09b17d 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -4,16 +4,23 @@
#include <chainparams.h>
#include <index/base.h>
+#include <interfaces/chain.h>
+#include <kernel/chain.h>
#include <node/blockstorage.h>
+#include <node/context.h>
#include <node/interface_ui.h>
#include <shutdown.h>
#include <tinyformat.h>
#include <util/syscall_sandbox.h>
+#include <util/system.h>
#include <util/thread.h>
#include <util/translation.h>
#include <validation.h> // For g_chainman
#include <warnings.h>
+#include <string>
+#include <utility>
+
using node::ReadBlockFromDisk;
constexpr uint8_t DB_BEST_BLOCK{'B'};
@@ -31,6 +38,15 @@ static void FatalError(const char* fmt, const Args&... args)
StartShutdown();
}
+CBlockLocator GetLocator(interfaces::Chain& chain, const uint256& block_hash)
+{
+ CBlockLocator locator;
+ bool found = chain.findBlock(block_hash, interfaces::FoundBlock().locator(locator));
+ assert(found);
+ assert(!locator.IsNull());
+ return locator;
+}
+
BaseIndex::DB::DB(const fs::path& path, size_t n_cache_size, bool f_memory, bool f_wipe, bool f_obfuscate) :
CDBWrapper(path, n_cache_size, f_memory, f_wipe, f_obfuscate)
{}
@@ -49,6 +65,9 @@ void BaseIndex::DB::WriteBestBlock(CDBBatch& batch, const CBlockLocator& locator
batch.Write(DB_BEST_BLOCK, locator);
}
+BaseIndex::BaseIndex(std::unique_ptr<interfaces::Chain> chain, std::string name)
+ : m_chain{std::move(chain)}, m_name{std::move(name)} {}
+
BaseIndex::~BaseIndex()
{
Interrupt();
@@ -69,6 +88,10 @@ bool BaseIndex::Init()
} else {
SetBestBlockIndex(m_chainstate->FindForkInGlobalIndex(locator));
}
+
+ // Note: this will latch to true immediately if the user starts up with an empty
+ // datadir and an index enabled. If this is the case, indexation will happen solely
+ // via `BlockConnected` signals until, possibly, the next restart.
m_synced = m_best_block_index.load() == active_chain.Tip();
if (!m_synced) {
bool prune_violation = false;
@@ -175,12 +198,15 @@ void BaseIndex::ThreadSync()
}
CBlock block;
+ interfaces::BlockInfo block_info = kernel::MakeBlockInfo(pindex);
if (!ReadBlockFromDisk(block, pindex, consensus_params)) {
FatalError("%s: Failed to read block %s from disk",
__func__, pindex->GetBlockHash().ToString());
return;
+ } else {
+ block_info.data = &block;
}
- if (!WriteBlock(block, pindex)) {
+ if (!CustomAppend(block_info)) {
FatalError("%s: Failed to write block %s to index database",
__func__, pindex->GetBlockHash().ToString());
return;
@@ -197,22 +223,20 @@ void BaseIndex::ThreadSync()
bool BaseIndex::Commit()
{
- CDBBatch batch(GetDB());
- if (!CommitInternal(batch) || !GetDB().WriteBatch(batch)) {
- return error("%s: Failed to commit latest %s state", __func__, GetName());
- }
- return true;
-}
-
-bool BaseIndex::CommitInternal(CDBBatch& batch)
-{
- LOCK(cs_main);
// Don't commit anything if we haven't indexed any block yet
// (this could happen if init is interrupted).
- if (m_best_block_index == nullptr) {
- return false;
+ bool ok = m_best_block_index != nullptr;
+ if (ok) {
+ CDBBatch batch(GetDB());
+ ok = CustomCommit(batch);
+ if (ok) {
+ GetDB().WriteBestBlock(batch, GetLocator(*m_chain, m_best_block_index.load()->GetBlockHash()));
+ ok = GetDB().WriteBatch(batch);
+ }
+ }
+ if (!ok) {
+ return error("%s: Failed to commit latest %s state", __func__, GetName());
}
- GetDB().WriteBestBlock(batch, m_chainstate->m_chain.GetLocator(m_best_block_index));
return true;
}
@@ -221,6 +245,10 @@ bool BaseIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_ti
assert(current_tip == m_best_block_index);
assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
+ if (!CustomRewind({current_tip->GetBlockHash(), current_tip->nHeight}, {new_tip->GetBlockHash(), new_tip->nHeight})) {
+ return false;
+ }
+
// In the case of a reorg, ensure persisted block locator is not stale.
// Pruning has a minimum of 288 blocks-to-keep and getting the index
// out of sync may be possible but a users fault.
@@ -268,8 +296,12 @@ void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const
return;
}
}
-
- if (WriteBlock(*block, pindex)) {
+ interfaces::BlockInfo block_info = kernel::MakeBlockInfo(pindex, block.get());
+ if (CustomAppend(block_info)) {
+ // Setting the best block index is intentionally the last step of this
+ // function, so BlockUntilSyncedToCurrentChain callers waiting for the
+ // best block index to be updated can rely on the block being fully
+ // processed, and the index object being safe to delete.
SetBestBlockIndex(pindex);
} else {
FatalError("%s: Failed to write block %s to index",
@@ -346,13 +378,18 @@ void BaseIndex::Interrupt()
m_interrupt();
}
-bool BaseIndex::Start(CChainState& active_chainstate)
+bool BaseIndex::Start()
{
- m_chainstate = &active_chainstate;
+ // m_chainstate member gives indexing code access to node internals. It is
+ // removed in followup https://github.com/bitcoin/bitcoin/pull/24230
+ m_chainstate = &m_chain->context()->chainman->ActiveChainstate();
// Need to register this ValidationInterface before running Init(), so that
// callbacks are not missed if Init sets m_synced to true.
RegisterValidationInterface(this);
- if (!Init()) {
+ if (!Init()) return false;
+
+ const CBlockIndex* index = m_best_block_index.load();
+ if (!CustomInit(index ? std::make_optional(interfaces::BlockKey{index->GetBlockHash(), index->nHeight}) : std::nullopt)) {
return false;
}
@@ -381,10 +418,17 @@ IndexSummary BaseIndex::GetSummary() const
void BaseIndex::SetBestBlockIndex(const CBlockIndex* block) {
assert(!node::fPruneMode || AllowPrune());
- m_best_block_index = block;
if (AllowPrune() && block) {
node::PruneLockInfo prune_lock;
prune_lock.height_first = block->nHeight;
WITH_LOCK(::cs_main, m_chainstate->m_blockman.UpdatePruneLock(GetName(), prune_lock));
}
+
+ // Intentionally set m_best_block_index as the last step in this function,
+ // after updating prune locks above, and after making any other references
+ // to *this, so the BlockUntilSyncedToCurrentChain function (which checks
+ // m_best_block_index as an optimization) can be used to wait for the last
+ // BlockConnected notification and safely assume that prune locks are
+ // updated and that the index object is safe to delete.
+ m_best_block_index = block;
}
diff --git a/src/index/base.h b/src/index/base.h
index a8f6a18c8d..349178a535 100644
--- a/src/index/base.h
+++ b/src/index/base.h
@@ -6,12 +6,18 @@
#define BITCOIN_INDEX_BASE_H
#include <dbwrapper.h>
+#include <interfaces/chain.h>
#include <threadinterrupt.h>
#include <validationinterface.h>
+#include <string>
+
class CBlock;
class CBlockIndex;
-class CChainState;
+class Chainstate;
+namespace interfaces {
+class Chain;
+} // namespace interfaces
struct IndexSummary {
std::string name;
@@ -51,6 +57,10 @@ private:
/// Whether the index is in sync with the main chain. The flag is flipped
/// from false to true once, after which point this starts processing
/// ValidationInterface notifications to stay in sync.
+ ///
+ /// Note that this will latch to true *immediately* upon startup if
+ /// `m_chainstate->m_chain` is empty, which will be the case upon startup
+ /// with an empty datadir if, e.g., `-txindex=1` is specified.
std::atomic<bool> m_synced{false};
/// The last block in the chain that the index is in sync with.
@@ -59,6 +69,9 @@ private:
std::thread m_thread_sync;
CThreadInterrupt m_interrupt;
+ /// Read best block locator and check that data needed to sync has not been pruned.
+ bool Init();
+
/// Sync the index with the block index starting from the current best block.
/// Intended to be run in its own thread, m_thread_sync, and can be
/// interrupted with m_interrupt. Once the index gets in sync, the m_synced
@@ -76,40 +89,44 @@ private:
/// getting corrupted.
bool Commit();
+ /// Loop over disconnected blocks and call CustomRewind.
+ bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip);
+
virtual bool AllowPrune() const = 0;
protected:
- CChainState* m_chainstate{nullptr};
+ std::unique_ptr<interfaces::Chain> m_chain;
+ Chainstate* m_chainstate{nullptr};
+ const std::string m_name;
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override;
void ChainStateFlushed(const CBlockLocator& locator) override;
- const CBlockIndex* CurrentIndex() { return m_best_block_index.load(); };
-
/// Initialize internal state from the database and block index.
- [[nodiscard]] virtual bool Init();
+ [[nodiscard]] virtual bool CustomInit(const std::optional<interfaces::BlockKey>& block) { return true; }
/// Write update index entries for a newly connected block.
- virtual bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) { return true; }
+ [[nodiscard]] virtual bool CustomAppend(const interfaces::BlockInfo& block) { return true; }
/// Virtual method called internally by Commit that can be overridden to atomically
/// commit more index state.
- virtual bool CommitInternal(CDBBatch& batch);
+ virtual bool CustomCommit(CDBBatch& batch) { return true; }
/// Rewind index to an earlier chain tip during a chain reorg. The tip must
/// be an ancestor of the current best block.
- virtual bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip);
+ [[nodiscard]] virtual bool CustomRewind(const interfaces::BlockKey& current_tip, const interfaces::BlockKey& new_tip) { return true; }
virtual DB& GetDB() const = 0;
/// Get the name of the index for display in logs.
- virtual const char* GetName() const = 0;
+ const std::string& GetName() const LIFETIMEBOUND { return m_name; }
/// Update the internal best block index as well as the prune lock.
void SetBestBlockIndex(const CBlockIndex* block);
public:
+ BaseIndex(std::unique_ptr<interfaces::Chain> chain, std::string name);
/// Destructor interrupts sync thread if running and blocks until it exits.
virtual ~BaseIndex();
@@ -124,7 +141,7 @@ public:
/// Start initializes the sync state and registers the instance as a
/// ValidationInterface so that it stays in sync with blockchain updates.
- [[nodiscard]] bool Start(CChainState& active_chainstate);
+ [[nodiscard]] bool Start();
/// Stops the instance from staying in sync with blockchain updates.
void Stop();
diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp
index c92b8c7e19..292e11c874 100644
--- a/src/index/blockfilterindex.cpp
+++ b/src/index/blockfilterindex.cpp
@@ -5,9 +5,11 @@
#include <map>
#include <dbwrapper.h>
+#include <hash.h>
#include <index/blockfilterindex.h>
#include <node/blockstorage.h>
#include <util/system.h>
+#include <validation.h>
using node::UndoReadFromDisk;
@@ -93,9 +95,10 @@ struct DBHashKey {
static std::map<BlockFilterType, BlockFilterIndex> g_filter_indexes;
-BlockFilterIndex::BlockFilterIndex(BlockFilterType filter_type,
+BlockFilterIndex::BlockFilterIndex(std::unique_ptr<interfaces::Chain> chain, BlockFilterType filter_type,
size_t n_cache_size, bool f_memory, bool f_wipe)
- : m_filter_type(filter_type)
+ : BaseIndex(std::move(chain), BlockFilterTypeName(filter_type) + " block filter index")
+ , m_filter_type(filter_type)
{
const std::string& filter_name = BlockFilterTypeName(filter_type);
if (filter_name.empty()) throw std::invalid_argument("unknown filter_type");
@@ -103,12 +106,11 @@ BlockFilterIndex::BlockFilterIndex(BlockFilterType filter_type,
fs::path path = gArgs.GetDataDirNet() / "indexes" / "blockfilter" / fs::u8path(filter_name);
fs::create_directories(path);
- m_name = filter_name + " block filter index";
m_db = std::make_unique<BaseIndex::DB>(path / "db", n_cache_size, f_memory, f_wipe);
m_filter_fileseq = std::make_unique<FlatFileSeq>(std::move(path), "fltr", FLTR_FILE_CHUNK_SIZE);
}
-bool BlockFilterIndex::Init()
+bool BlockFilterIndex::CustomInit(const std::optional<interfaces::BlockKey>& block)
{
if (!m_db->Read(DB_FILTER_POS, m_next_filter_pos)) {
// Check that the cause of the read failure is that the key does not exist. Any other errors
@@ -123,15 +125,15 @@ bool BlockFilterIndex::Init()
m_next_filter_pos.nFile = 0;
m_next_filter_pos.nPos = 0;
}
- return BaseIndex::Init();
+ return true;
}
-bool BlockFilterIndex::CommitInternal(CDBBatch& batch)
+bool BlockFilterIndex::CustomCommit(CDBBatch& batch)
{
const FlatFilePos& pos = m_next_filter_pos;
// Flush current filter file to disk.
- CAutoFile file(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ AutoFile file{m_filter_fileseq->Open(pos)};
if (file.IsNull()) {
return error("%s: Failed to open filter file %d", __func__, pos.nFile);
}
@@ -140,21 +142,25 @@ bool BlockFilterIndex::CommitInternal(CDBBatch& batch)
}
batch.Write(DB_FILTER_POS, pos);
- return BaseIndex::CommitInternal(batch);
+ return true;
}
-bool BlockFilterIndex::ReadFilterFromDisk(const FlatFilePos& pos, BlockFilter& filter) const
+bool BlockFilterIndex::ReadFilterFromDisk(const FlatFilePos& pos, const uint256& hash, BlockFilter& filter) const
{
- CAutoFile filein(m_filter_fileseq->Open(pos, true), SER_DISK, CLIENT_VERSION);
+ AutoFile filein{m_filter_fileseq->Open(pos, true)};
if (filein.IsNull()) {
return false;
}
+ // Check that the hash of the encoded_filter matches the one stored in the db.
uint256 block_hash;
std::vector<uint8_t> encoded_filter;
try {
filein >> block_hash >> encoded_filter;
- filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter));
+ uint256 result;
+ CHash256().Write(encoded_filter).Finalize(result);
+ if (result != hash) return error("Checksum mismatch in filter decode.");
+ filter = BlockFilter(GetFilterType(), block_hash, std::move(encoded_filter), /*skip_decode_check=*/true);
}
catch (const std::exception& e) {
return error("%s: Failed to deserialize block filter from disk: %s", __func__, e.what());
@@ -173,7 +179,7 @@ size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter&
// If writing the filter would overflow the file, flush and move to the next one.
if (pos.nPos + data_size > MAX_FLTR_FILE_SIZE) {
- CAutoFile last_file(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ AutoFile last_file{m_filter_fileseq->Open(pos)};
if (last_file.IsNull()) {
LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile);
return 0;
@@ -199,7 +205,7 @@ size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter&
return 0;
}
- CAutoFile fileout(m_filter_fileseq->Open(pos), SER_DISK, CLIENT_VERSION);
+ AutoFile fileout{m_filter_fileseq->Open(pos)};
if (fileout.IsNull()) {
LogPrintf("%s: Failed to open filter file %d\n", __func__, pos.nFile);
return 0;
@@ -209,22 +215,25 @@ size_t BlockFilterIndex::WriteFilterToDisk(FlatFilePos& pos, const BlockFilter&
return data_size;
}
-bool BlockFilterIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
+bool BlockFilterIndex::CustomAppend(const interfaces::BlockInfo& block)
{
CBlockUndo block_undo;
uint256 prev_header;
- if (pindex->nHeight > 0) {
+ if (block.height > 0) {
+ // pindex variable gives indexing code access to node internals. It
+ // will be removed in upcoming commit
+ const CBlockIndex* pindex = WITH_LOCK(cs_main, return m_chainstate->m_blockman.LookupBlockIndex(block.hash));
if (!UndoReadFromDisk(block_undo, pindex)) {
return false;
}
std::pair<uint256, DBVal> read_out;
- if (!m_db->Read(DBHeightKey(pindex->nHeight - 1), read_out)) {
+ if (!m_db->Read(DBHeightKey(block.height - 1), read_out)) {
return false;
}
- uint256 expected_block_hash = pindex->pprev->GetBlockHash();
+ uint256 expected_block_hash = *Assert(block.prev_hash);
if (read_out.first != expected_block_hash) {
return error("%s: previous block header belongs to unexpected block %s; expected %s",
__func__, read_out.first.ToString(), expected_block_hash.ToString());
@@ -233,18 +242,18 @@ bool BlockFilterIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex
prev_header = read_out.second.header;
}
- BlockFilter filter(m_filter_type, block, block_undo);
+ BlockFilter filter(m_filter_type, *Assert(block.data), block_undo);
size_t bytes_written = WriteFilterToDisk(m_next_filter_pos, filter);
if (bytes_written == 0) return false;
std::pair<uint256, DBVal> value;
- value.first = pindex->GetBlockHash();
+ value.first = block.hash;
value.second.hash = filter.GetHash();
value.second.header = filter.ComputeHeader(prev_header);
value.second.pos = m_next_filter_pos;
- if (!m_db->Write(DBHeightKey(pindex->nHeight), value)) {
+ if (!m_db->Write(DBHeightKey(block.height), value)) {
return false;
}
@@ -278,17 +287,15 @@ static bool CopyHeightIndexToHashIndex(CDBIterator& db_it, CDBBatch& batch,
return true;
}
-bool BlockFilterIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
+bool BlockFilterIndex::CustomRewind(const interfaces::BlockKey& current_tip, const interfaces::BlockKey& new_tip)
{
- assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
-
CDBBatch batch(*m_db);
std::unique_ptr<CDBIterator> db_it(m_db->NewIterator());
// During a reorg, we need to copy all filters for blocks that are getting disconnected from the
// height index to the hash index so we can still find them when the height index entries are
// overwritten.
- if (!CopyHeightIndexToHashIndex(*db_it, batch, m_name, new_tip->nHeight, current_tip->nHeight)) {
+ if (!CopyHeightIndexToHashIndex(*db_it, batch, m_name, new_tip.height, current_tip.height)) {
return false;
}
@@ -298,7 +305,7 @@ bool BlockFilterIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex*
batch.Write(DB_FILTER_POS, m_next_filter_pos);
if (!m_db->WriteBatch(batch)) return false;
- return BaseIndex::Rewind(current_tip, new_tip);
+ return true;
}
static bool LookupOne(const CDBWrapper& db, const CBlockIndex* block_index, DBVal& result)
@@ -381,7 +388,7 @@ bool BlockFilterIndex::LookupFilter(const CBlockIndex* block_index, BlockFilter&
return false;
}
- return ReadFilterFromDisk(entry.pos, filter_out);
+ return ReadFilterFromDisk(entry.pos, entry.hash, filter_out);
}
bool BlockFilterIndex::LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out)
@@ -425,7 +432,7 @@ bool BlockFilterIndex::LookupFilterRange(int start_height, const CBlockIndex* st
filters_out.resize(entries.size());
auto filter_pos_it = filters_out.begin();
for (const auto& entry : entries) {
- if (!ReadFilterFromDisk(entry.pos, *filter_pos_it)) {
+ if (!ReadFilterFromDisk(entry.pos, entry.hash, *filter_pos_it)) {
return false;
}
++filter_pos_it;
@@ -462,12 +469,12 @@ void ForEachBlockFilterIndex(std::function<void (BlockFilterIndex&)> fn)
for (auto& entry : g_filter_indexes) fn(entry.second);
}
-bool InitBlockFilterIndex(BlockFilterType filter_type,
+bool InitBlockFilterIndex(std::function<std::unique_ptr<interfaces::Chain>()> make_chain, BlockFilterType filter_type,
size_t n_cache_size, bool f_memory, bool f_wipe)
{
auto result = g_filter_indexes.emplace(std::piecewise_construct,
std::forward_as_tuple(filter_type),
- std::forward_as_tuple(filter_type,
+ std::forward_as_tuple(make_chain(), filter_type,
n_cache_size, f_memory, f_wipe));
return result.second;
}
diff --git a/src/index/blockfilterindex.h b/src/index/blockfilterindex.h
index 6deff59000..5af4671091 100644
--- a/src/index/blockfilterindex.h
+++ b/src/index/blockfilterindex.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_INDEX_BLOCKFILTERINDEX_H
#define BITCOIN_INDEX_BLOCKFILTERINDEX_H
+#include <attributes.h>
#include <blockfilter.h>
#include <chain.h>
#include <flatfile.h>
@@ -25,13 +26,12 @@ class BlockFilterIndex final : public BaseIndex
{
private:
BlockFilterType m_filter_type;
- std::string m_name;
std::unique_ptr<BaseIndex::DB> m_db;
FlatFilePos m_next_filter_pos;
std::unique_ptr<FlatFileSeq> m_filter_fileseq;
- bool ReadFilterFromDisk(const FlatFilePos& pos, BlockFilter& filter) const;
+ bool ReadFilterFromDisk(const FlatFilePos& pos, const uint256& hash, BlockFilter& filter) const;
size_t WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter);
Mutex m_cs_headers_cache;
@@ -41,21 +41,19 @@ private:
bool AllowPrune() const override { return true; }
protected:
- bool Init() override;
+ bool CustomInit(const std::optional<interfaces::BlockKey>& block) override;
- bool CommitInternal(CDBBatch& batch) override;
+ bool CustomCommit(CDBBatch& batch) override;
- bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) override;
+ bool CustomAppend(const interfaces::BlockInfo& block) override;
- bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip) override;
+ bool CustomRewind(const interfaces::BlockKey& current_tip, const interfaces::BlockKey& new_tip) override;
- BaseIndex::DB& GetDB() const override { return *m_db; }
-
- const char* GetName() const override { return m_name.c_str(); }
+ BaseIndex::DB& GetDB() const LIFETIMEBOUND override { return *m_db; }
public:
/** Constructs the index, which becomes available to be queried. */
- explicit BlockFilterIndex(BlockFilterType filter_type,
+ explicit BlockFilterIndex(std::unique_ptr<interfaces::Chain> chain, BlockFilterType filter_type,
size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
BlockFilterType GetFilterType() const { return m_filter_type; }
@@ -88,7 +86,7 @@ void ForEachBlockFilterIndex(std::function<void (BlockFilterIndex&)> fn);
* Initialize a block filter index for the given type if one does not already exist. Returns true if
* a new index is created and false if one has already been initialized.
*/
-bool InitBlockFilterIndex(BlockFilterType filter_type,
+bool InitBlockFilterIndex(std::function<std::unique_ptr<interfaces::Chain>()> make_chain, BlockFilterType filter_type,
size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
/**
diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp
index 687e330fe0..d3559b1b75 100644
--- a/src/index/coinstatsindex.cpp
+++ b/src/index/coinstatsindex.cpp
@@ -6,10 +6,12 @@
#include <coins.h>
#include <crypto/muhash.h>
#include <index/coinstatsindex.h>
+#include <kernel/coinstats.h>
#include <node/blockstorage.h>
#include <serialize.h>
#include <txdb.h>
#include <undo.h>
+#include <util/system.h>
#include <validation.h>
using kernel::CCoinsStats;
@@ -102,7 +104,8 @@ struct DBHashKey {
std::unique_ptr<CoinStatsIndex> g_coin_stats_index;
-CoinStatsIndex::CoinStatsIndex(size_t n_cache_size, bool f_memory, bool f_wipe)
+CoinStatsIndex::CoinStatsIndex(std::unique_ptr<interfaces::Chain> chain, size_t n_cache_size, bool f_memory, bool f_wipe)
+ : BaseIndex(std::move(chain), "coinstatsindex")
{
fs::path path{gArgs.GetDataDirNet() / "indexes" / "coinstats"};
fs::create_directories(path);
@@ -110,24 +113,27 @@ CoinStatsIndex::CoinStatsIndex(size_t n_cache_size, bool f_memory, bool f_wipe)
m_db = std::make_unique<CoinStatsIndex::DB>(path / "db", n_cache_size, f_memory, f_wipe);
}
-bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
+bool CoinStatsIndex::CustomAppend(const interfaces::BlockInfo& block)
{
CBlockUndo block_undo;
- const CAmount block_subsidy{GetBlockSubsidy(pindex->nHeight, Params().GetConsensus())};
+ const CAmount block_subsidy{GetBlockSubsidy(block.height, Params().GetConsensus())};
m_total_subsidy += block_subsidy;
// Ignore genesis block
- if (pindex->nHeight > 0) {
+ if (block.height > 0) {
+ // pindex variable gives indexing code access to node internals. It
+ // will be removed in upcoming commit
+ const CBlockIndex* pindex = WITH_LOCK(cs_main, return m_chainstate->m_blockman.LookupBlockIndex(block.hash));
if (!UndoReadFromDisk(block_undo, pindex)) {
return false;
}
std::pair<uint256, DBVal> read_out;
- if (!m_db->Read(DBHeightKey(pindex->nHeight - 1), read_out)) {
+ if (!m_db->Read(DBHeightKey(block.height - 1), read_out)) {
return false;
}
- uint256 expected_block_hash{pindex->pprev->GetBlockHash()};
+ uint256 expected_block_hash{*Assert(block.prev_hash)};
if (read_out.first != expected_block_hash) {
LogPrintf("WARNING: previous block header belongs to unexpected block %s; expected %s\n",
read_out.first.ToString(), expected_block_hash.ToString());
@@ -139,12 +145,13 @@ bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
}
// TODO: Deduplicate BIP30 related code
- bool is_bip30_block{(pindex->nHeight == 91722 && pindex->GetBlockHash() == uint256S("0x00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e")) ||
- (pindex->nHeight == 91812 && pindex->GetBlockHash() == uint256S("0x00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"))};
+ bool is_bip30_block{(block.height == 91722 && block.hash == uint256S("0x00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e")) ||
+ (block.height == 91812 && block.hash == uint256S("0x00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"))};
// Add the new utxos created from the block
- for (size_t i = 0; i < block.vtx.size(); ++i) {
- const auto& tx{block.vtx.at(i)};
+ assert(block.data);
+ for (size_t i = 0; i < block.data->vtx.size(); ++i) {
+ const auto& tx{block.data->vtx.at(i)};
// Skip duplicate txid coinbase transactions (BIP30).
if (is_bip30_block && tx->IsCoinBase()) {
@@ -155,7 +162,7 @@ bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
for (uint32_t j = 0; j < tx->vout.size(); ++j) {
const CTxOut& out{tx->vout[j]};
- Coin coin{out, pindex->nHeight, tx->IsCoinBase()};
+ Coin coin{out, block.height, tx->IsCoinBase()};
COutPoint outpoint{tx->GetHash(), j};
// Skip unspendable coins
@@ -211,7 +218,7 @@ bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
m_total_unspendables_unclaimed_rewards += unclaimed_rewards;
std::pair<uint256, DBVal> value;
- value.first = pindex->GetBlockHash();
+ value.first = block.hash;
value.second.transaction_output_count = m_transaction_output_count;
value.second.bogo_size = m_bogo_size;
value.second.total_amount = m_total_amount;
@@ -231,7 +238,7 @@ bool CoinStatsIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
// Intentionally do not update DB_MUHASH here so it stays in sync with
// DB_BEST_BLOCK, and the index is not corrupted if there is an unclean shutdown.
- return m_db->Write(DBHeightKey(pindex->nHeight), value);
+ return m_db->Write(DBHeightKey(block.height), value);
}
static bool CopyHeightIndexToHashIndex(CDBIterator& db_it, CDBBatch& batch,
@@ -260,17 +267,15 @@ static bool CopyHeightIndexToHashIndex(CDBIterator& db_it, CDBBatch& batch,
return true;
}
-bool CoinStatsIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip)
+bool CoinStatsIndex::CustomRewind(const interfaces::BlockKey& current_tip, const interfaces::BlockKey& new_tip)
{
- assert(current_tip->GetAncestor(new_tip->nHeight) == new_tip);
-
CDBBatch batch(*m_db);
std::unique_ptr<CDBIterator> db_it(m_db->NewIterator());
// During a reorg, we need to copy all hash digests for blocks that are
// getting disconnected from the height index to the hash index so we can
// still find them when the height index entries are overwritten.
- if (!CopyHeightIndexToHashIndex(*db_it, batch, m_name, new_tip->nHeight, current_tip->nHeight)) {
+ if (!CopyHeightIndexToHashIndex(*db_it, batch, m_name, new_tip.height, current_tip.height)) {
return false;
}
@@ -278,7 +283,8 @@ bool CoinStatsIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* n
{
LOCK(cs_main);
- const CBlockIndex* iter_tip{m_chainstate->m_blockman.LookupBlockIndex(current_tip->GetBlockHash())};
+ const CBlockIndex* iter_tip{m_chainstate->m_blockman.LookupBlockIndex(current_tip.hash)};
+ const CBlockIndex* new_tip_index{m_chainstate->m_blockman.LookupBlockIndex(new_tip.hash)};
const auto& consensus_params{Params().GetConsensus()};
do {
@@ -292,38 +298,38 @@ bool CoinStatsIndex::Rewind(const CBlockIndex* current_tip, const CBlockIndex* n
ReverseBlock(block, iter_tip);
iter_tip = iter_tip->GetAncestor(iter_tip->nHeight - 1);
- } while (new_tip != iter_tip);
+ } while (new_tip_index != iter_tip);
}
- return BaseIndex::Rewind(current_tip, new_tip);
+ return true;
}
-static bool LookUpOne(const CDBWrapper& db, const CBlockIndex* block_index, DBVal& result)
+static bool LookUpOne(const CDBWrapper& db, const interfaces::BlockKey& block, DBVal& result)
{
// First check if the result is stored under the height index and the value
// there matches the block hash. This should be the case if the block is on
// the active chain.
std::pair<uint256, DBVal> read_out;
- if (!db.Read(DBHeightKey(block_index->nHeight), read_out)) {
+ if (!db.Read(DBHeightKey(block.height), read_out)) {
return false;
}
- if (read_out.first == block_index->GetBlockHash()) {
+ if (read_out.first == block.hash) {
result = std::move(read_out.second);
return true;
}
// If value at the height index corresponds to an different block, the
// result will be stored in the hash index.
- return db.Read(DBHashKey(block_index->GetBlockHash()), result);
+ return db.Read(DBHashKey(block.hash), result);
}
-std::optional<CCoinsStats> CoinStatsIndex::LookUpStats(const CBlockIndex* block_index) const
+std::optional<CCoinsStats> CoinStatsIndex::LookUpStats(const CBlockIndex& block_index) const
{
- CCoinsStats stats{Assert(block_index)->nHeight, block_index->GetBlockHash()};
+ CCoinsStats stats{block_index.nHeight, block_index.GetBlockHash()};
stats.index_used = true;
DBVal entry;
- if (!LookUpOne(*m_db, block_index, entry)) {
+ if (!LookUpOne(*m_db, {block_index.GetBlockHash(), block_index.nHeight}, entry)) {
return std::nullopt;
}
@@ -344,7 +350,7 @@ std::optional<CCoinsStats> CoinStatsIndex::LookUpStats(const CBlockIndex* block_
return stats;
}
-bool CoinStatsIndex::Init()
+bool CoinStatsIndex::CustomInit(const std::optional<interfaces::BlockKey>& block)
{
if (!m_db->Read(DB_MUHASH, m_muhash)) {
// Check that the cause of the read failure is that the key does not
@@ -356,13 +362,9 @@ bool CoinStatsIndex::Init()
}
}
- if (!BaseIndex::Init()) return false;
-
- const CBlockIndex* pindex{CurrentIndex()};
-
- if (pindex) {
+ if (block) {
DBVal entry;
- if (!LookUpOne(*m_db, pindex, entry)) {
+ if (!LookUpOne(*m_db, *block, entry)) {
return error("%s: Cannot read current %s state; index may be corrupted",
__func__, GetName());
}
@@ -391,12 +393,12 @@ bool CoinStatsIndex::Init()
return true;
}
-bool CoinStatsIndex::CommitInternal(CDBBatch& batch)
+bool CoinStatsIndex::CustomCommit(CDBBatch& batch)
{
// DB_MUHASH should always be committed in a batch together with DB_BEST_BLOCK
// to prevent an inconsistent state of the DB.
batch.Write(DB_MUHASH, m_muhash);
- return BaseIndex::CommitInternal(batch);
+ return true;
}
// Reverse a single block as part of a reorg
diff --git a/src/index/coinstatsindex.h b/src/index/coinstatsindex.h
index cae052d913..fa59cb1ab1 100644
--- a/src/index/coinstatsindex.h
+++ b/src/index/coinstatsindex.h
@@ -5,11 +5,14 @@
#ifndef BITCOIN_INDEX_COINSTATSINDEX_H
#define BITCOIN_INDEX_COINSTATSINDEX_H
-#include <chain.h>
#include <crypto/muhash.h>
-#include <flatfile.h>
#include <index/base.h>
-#include <kernel/coinstats.h>
+
+class CBlockIndex;
+class CDBBatch;
+namespace kernel {
+struct CCoinsStats;
+}
/**
* CoinStatsIndex maintains statistics on the UTXO set.
@@ -17,7 +20,6 @@
class CoinStatsIndex final : public BaseIndex
{
private:
- std::string m_name;
std::unique_ptr<BaseIndex::DB> m_db;
MuHash3072 m_muhash;
@@ -39,24 +41,22 @@ private:
bool AllowPrune() const override { return true; }
protected:
- bool Init() override;
+ bool CustomInit(const std::optional<interfaces::BlockKey>& block) override;
- bool CommitInternal(CDBBatch& batch) override;
+ bool CustomCommit(CDBBatch& batch) override;
- bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) override;
+ bool CustomAppend(const interfaces::BlockInfo& block) override;
- bool Rewind(const CBlockIndex* current_tip, const CBlockIndex* new_tip) override;
+ bool CustomRewind(const interfaces::BlockKey& current_tip, const interfaces::BlockKey& new_tip) override;
BaseIndex::DB& GetDB() const override { return *m_db; }
- const char* GetName() const override { return "coinstatsindex"; }
-
public:
// Constructs the index, which becomes available to be queried.
- explicit CoinStatsIndex(size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
+ explicit CoinStatsIndex(std::unique_ptr<interfaces::Chain> chain, size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
// Look up stats for a specific block using CBlockIndex
- std::optional<kernel::CCoinsStats> LookUpStats(const CBlockIndex* block_index) const;
+ std::optional<kernel::CCoinsStats> LookUpStats(const CBlockIndex& block_index) const;
};
/// The global UTXO set hash object.
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 97c11c4383..a4fe1b611e 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -48,23 +48,22 @@ bool TxIndex::DB::WriteTxs(const std::vector<std::pair<uint256, CDiskTxPos>>& v_
return WriteBatch(batch);
}
-TxIndex::TxIndex(size_t n_cache_size, bool f_memory, bool f_wipe)
- : m_db(std::make_unique<TxIndex::DB>(n_cache_size, f_memory, f_wipe))
+TxIndex::TxIndex(std::unique_ptr<interfaces::Chain> chain, size_t n_cache_size, bool f_memory, bool f_wipe)
+ : BaseIndex(std::move(chain), "txindex"), m_db(std::make_unique<TxIndex::DB>(n_cache_size, f_memory, f_wipe))
{}
TxIndex::~TxIndex() = default;
-bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
+bool TxIndex::CustomAppend(const interfaces::BlockInfo& block)
{
// Exclude genesis block transaction because outputs are not spendable.
- if (pindex->nHeight == 0) return true;
+ if (block.height == 0) return true;
- CDiskTxPos pos{
- WITH_LOCK(::cs_main, return pindex->GetBlockPos()),
- GetSizeOfCompactSize(block.vtx.size())};
+ assert(block.data);
+ CDiskTxPos pos({block.file_number, block.data_pos}, GetSizeOfCompactSize(block.data->vtx.size()));
std::vector<std::pair<uint256, CDiskTxPos>> vPos;
- vPos.reserve(block.vtx.size());
- for (const auto& tx : block.vtx) {
+ vPos.reserve(block.data->vtx.size());
+ for (const auto& tx : block.data->vtx) {
vPos.emplace_back(tx->GetHash(), pos);
pos.nTxOffset += ::GetSerializeSize(*tx, CLIENT_VERSION);
}
diff --git a/src/index/txindex.h b/src/index/txindex.h
index ec339abaa1..8c1aa00033 100644
--- a/src/index/txindex.h
+++ b/src/index/txindex.h
@@ -23,15 +23,13 @@ private:
bool AllowPrune() const override { return false; }
protected:
- bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) override;
+ bool CustomAppend(const interfaces::BlockInfo& block) override;
BaseIndex::DB& GetDB() const override;
- const char* GetName() const override { return "txindex"; }
-
public:
/// Constructs the index, which becomes available to be queried.
- explicit TxIndex(size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
+ explicit TxIndex(std::unique_ptr<interfaces::Chain> chain, size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
// Destructor is declared because this class contains a unique_ptr to an incomplete type.
virtual ~TxIndex() override;
diff --git a/src/init.cpp b/src/init.cpp
index f20c55dcb1..25b40c6c6e 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -10,6 +10,8 @@
#include <init.h>
#include <kernel/checks.h>
+#include <kernel/mempool_persist.h>
+#include <kernel/validation_cache_sizes.h>
#include <addrman.h>
#include <banman.h>
@@ -39,10 +41,14 @@
#include <node/caches.h>
#include <node/chainstate.h>
#include <node/context.h>
-#include <node/miner.h>
#include <node/interface_ui.h>
+#include <node/mempool_args.h>
+#include <node/mempool_persist_args.h>
+#include <node/miner.h>
+#include <node/validation_cache_args.h>
#include <policy/feerate.h>
#include <policy/fees.h>
+#include <policy/fees_args.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <protocol.h>
@@ -100,14 +106,18 @@
#include <zmq/zmqrpc.h>
#endif
+using kernel::DumpMempool;
+using kernel::ValidationCacheSizes;
+
+using node::ApplyArgsManOptions;
using node::CacheSizes;
using node::CalculateCacheSizes;
-using node::ChainstateLoadVerifyError;
-using node::ChainstateLoadingError;
-using node::CleanupBlockRevFiles;
+using node::DEFAULT_PERSIST_MEMPOOL;
using node::DEFAULT_PRINTPRIORITY;
using node::DEFAULT_STOPAFTERBLOCKIMPORT;
using node::LoadChainstate;
+using node::MempoolPath;
+using node::ShouldPersistMempool;
using node::NodeContext;
using node::ThreadImport;
using node::VerifyLoadedChainstate;
@@ -243,8 +253,8 @@ void Shutdown(NodeContext& node)
node.addrman.reset();
node.netgroupman.reset();
- if (node.mempool && node.mempool->IsLoaded() && node.args->GetBoolArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
- DumpMempool(*node.mempool);
+ if (node.mempool && node.mempool->GetLoadTried() && ShouldPersistMempool(*node.args)) {
+ DumpMempool(*node.mempool, MempoolPath(*node.args));
}
// Drop transactions we were still watching, and record fee estimations.
@@ -253,7 +263,7 @@ void Shutdown(NodeContext& node)
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
if (node.chainman) {
LOCK(cs_main);
- for (CChainState* chainstate : node.chainman->GetAll()) {
+ for (Chainstate* chainstate : node.chainman->GetAll()) {
if (chainstate->CanFlushToDisk()) {
chainstate->ForceFlushStateToDisk();
}
@@ -284,7 +294,7 @@ void Shutdown(NodeContext& node)
if (node.chainman) {
LOCK(cs_main);
- for (CChainState* chainstate : node.chainman->GetAll()) {
+ for (Chainstate* chainstate : node.chainman->GetAll()) {
if (chainstate->CanFlushToDisk()) {
chainstate->ForceFlushStateToDisk();
chainstate->ResetCoinsViews();
@@ -413,9 +423,9 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (%d to %d, default: %d). In addition, unused mempool memory is shared for this cache (see -maxmempool).", nMinDbCache, nMaxDbCache, nDefaultDbCache), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-loadblock=<file>", "Imports blocks from external file on startup", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE_MB), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-maxorphantx=<n>", strprintf("Keep at most <n> unconnectable transactions in memory (default: %u)", DEFAULT_MAX_ORPHAN_TRANSACTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
+ argsman.AddArg("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY_HOURS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet: %s, signet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex(), signetChainParams->GetConsensus().nMinimumChainWork.GetHex()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
argsman.AddArg("-par=<n>", strprintf("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)",
-GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -466,7 +476,6 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-onlynet=<net>", "Make automatic outbound connections only to network <net> (" + Join(GetNetworkNames(), ", ") + "). Inbound and manual connections are not affected by this option. It can be specified multiple times to allow multiple networks.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
- argsman.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
// TODO: remove the sentence "Nodes not using ... incoming connections." once the changes from
// https://github.com/bitcoin/bitcoin/pull/23542 have become widespread.
argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port>. Nodes not using the default ports (default: %u, testnet: %u, signet: %u, regtest: %u) are unlikely to get incoming connections. Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
@@ -536,13 +545,13 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", DEFAULT_STOPATHEIGHT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT_KVB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT_KVB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-addrmantest", "Allows to test address relay on localhost", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-capturemessages", "Capture all P2P messages to disk", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-mocktime=<n>", "Replace actual time with " + UNIX_EPOCH_TIME + " (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_BYTES >> 20), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-printpriority", strprintf("Log transaction fee rate in " + CURRENCY_UNIT + "/kvB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
@@ -550,11 +559,14 @@ void SetupServerArgs(ArgsManager& argsman)
SetupChainParamsBaseOptions(argsman);
argsman.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !testnetChainParams->RequireStandard()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
- argsman.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
+ argsman.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define cost of relay, used for mempool limiting and replacement policy. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
+ argsman.AddArg("-mempoolfullrbf", strprintf("Accept transaction replace-by-fee without requiring replaceability signaling (default: %u)", DEFAULT_MEMPOOL_FULL_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
+ argsman.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY,
+ OptionsCategory::NODE_RELAY);
argsman.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kvB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted inbound peers with default permissions. This will relay transactions even if the transactions were already in the mempool. (default: %d)", DEFAULT_WHITELISTFORCERELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
@@ -712,6 +724,16 @@ void InitParameterInteraction(ArgsManager& args)
if (args.SoftSetBoolArg("-whitelistrelay", true))
LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__);
}
+ if (args.IsArgSet("-onlynet")) {
+ const auto onlynets = args.GetArgs("-onlynet");
+ bool clearnet_reachable = std::any_of(onlynets.begin(), onlynets.end(), [](const auto& net) {
+ const auto n = ParseNetwork(net);
+ return n == NET_IPV4 || n == NET_IPV6;
+ });
+ if (!clearnet_reachable && args.SoftSetBoolArg("-dnsseed", false)) {
+ LogPrintf("%s: parameter interaction: -onlynet excludes IPv4 and IPv6 -> setting -dnsseed=0\n", __func__);
+ }
+ }
}
/**
@@ -731,7 +753,7 @@ namespace { // Variables internal to initialization process only
int nMaxConnections;
int nUserMaxConnections;
int nFD;
-ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED | NODE_WITNESS);
+ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
int64_t peer_connect_timeout;
std::set<BlockFilterType> g_enabled_filter_types;
@@ -904,15 +926,12 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
// ********************************************************* Step 3: parameter-to-internal-flags
init::SetLoggingCategories(args);
+ init::SetLoggingLevel(args);
fCheckBlockIndex = args.GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks());
fCheckpointsEnabled = args.GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED);
hashAssumeValid = uint256S(args.GetArg("-assumevalid", chainparams.GetConsensus().defaultAssumeValid.GetHex()));
- if (!hashAssumeValid.IsNull())
- LogPrintf("Assuming ancestors of block %s have valid signatures.\n", hashAssumeValid.GetHex());
- else
- LogPrintf("Validating signatures for all blocks.\n");
if (args.IsArgSet("-minimumchainwork")) {
const std::string minChainWorkStr = args.GetArg("-minimumchainwork", "");
@@ -923,25 +942,6 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
} else {
nMinimumChainWork = UintToArith256(chainparams.GetConsensus().nMinimumChainWork);
}
- LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex());
- if (nMinimumChainWork < UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) {
- LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
- }
-
- // mempool limits
- int64_t nMempoolSizeMax = args.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
- int64_t nMempoolSizeMin = args.GetIntArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40;
- if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin)
- return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(nMempoolSizeMin / 1000000.0)));
- // incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool
- // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
- if (args.IsArgSet("-incrementalrelayfee")) {
- if (std::optional<CAmount> inc_relay_fee = ParseMoney(args.GetArg("-incrementalrelayfee", ""))) {
- ::incrementalRelayFee = CFeeRate{inc_relay_fee.value()};
- } else {
- return InitError(AmountErrMsg("incrementalrelayfee", args.GetArg("-incrementalrelayfee", "")));
- }
- }
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
int64_t nPruneArg = args.GetIntArg("-prune", 0);
@@ -950,14 +950,12 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
}
nPruneTarget = (uint64_t) nPruneArg * 1024 * 1024;
if (nPruneArg == 1) { // manual pruning: -prune=1
- LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
nPruneTarget = std::numeric_limits<uint64_t>::max();
fPruneMode = true;
} else if (nPruneTarget) {
if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) {
return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
}
- LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);
fPruneMode = true;
}
@@ -968,20 +966,7 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
peer_connect_timeout = args.GetIntArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT);
if (peer_connect_timeout <= 0) {
- return InitError(Untranslated("peertimeout cannot be configured with a negative value."));
- }
-
- if (args.IsArgSet("-minrelaytxfee")) {
- if (std::optional<CAmount> min_relay_fee = ParseMoney(args.GetArg("-minrelaytxfee", ""))) {
- // High fee check is done afterward in CWallet::Create()
- ::minRelayTxFee = CFeeRate{min_relay_fee.value()};
- } else {
- return InitError(AmountErrMsg("minrelaytxfee", args.GetArg("-minrelaytxfee", "")));
- }
- } else if (incrementalRelayFee > ::minRelayTxFee) {
- // Allow only setting incrementalRelayFee to control both
- ::minRelayTxFee = incrementalRelayFee;
- LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n",::minRelayTxFee.ToString());
+ return InitError(Untranslated("peertimeout must be a positive integer."));
}
// Sanity check argument for min fee for including tx in block
@@ -992,28 +977,10 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
}
}
- // Feerate used to define dust. Shouldn't be changed lightly as old
- // implementations may inadvertently create non-standard transactions
- if (args.IsArgSet("-dustrelayfee")) {
- if (std::optional<CAmount> parsed = ParseMoney(args.GetArg("-dustrelayfee", ""))) {
- dustRelayFee = CFeeRate{parsed.value()};
- } else {
- return InitError(AmountErrMsg("dustrelayfee", args.GetArg("-dustrelayfee", "")));
- }
- }
-
- fRequireStandard = !args.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
- if (!chainparams.IsTestChain() && !fRequireStandard) {
- return InitError(strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString()));
- }
nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
if (!g_wallet_init_interface.ParameterInteraction()) return false;
- fIsBareMultisigStd = args.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
- fAcceptDatacarrier = args.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
- nMaxDatacarrierBytes = args.GetIntArg("-datacarriersize", nMaxDatacarrierBytes);
-
// Option to startup with mocktime set (used for regression testing):
SetMockTime(args.GetIntArg("-mocktime", 0)); // SetMockTime(0) is a no-op
@@ -1081,7 +1048,7 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
static bool LockDataDirectory(bool probeOnly)
{
// Make sure only a single Bitcoin process is using the data directory.
- fs::path datadir = gArgs.GetDataDirNet();
+ const fs::path& datadir = gArgs.GetDataDirNet();
if (!DirIsWritable(datadir)) {
return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), fs::PathToString(datadir)));
}
@@ -1094,21 +1061,8 @@ static bool LockDataDirectory(bool probeOnly)
bool AppInitSanityChecks(const kernel::Context& kernel)
{
// ********************************************************* Step 4: sanity checks
- auto maybe_error = kernel::SanityChecks(kernel);
-
- if (maybe_error.has_value()) {
- switch (maybe_error.value()) {
- case kernel::SanityCheckError::ERROR_ECC:
- InitError(Untranslated("Elliptic curve cryptography sanity check failure. Aborting."));
- break;
- case kernel::SanityCheckError::ERROR_RANDOM:
- InitError(Untranslated("OS cryptographic RNG sanity check failure. Aborting."));
- break;
- case kernel::SanityCheckError::ERROR_CHRONO:
- InitError(Untranslated("Clock epoch mismatch. Aborting."));
- break;
- } // no default case, so the compiler can warn about missing cases
-
+ if (auto error = kernel::SanityChecks(kernel)) {
+ InitError(*error);
return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), PACKAGE_NAME));
}
@@ -1167,8 +1121,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
args.GetArg("-datadir", ""), fs::PathToString(fs::current_path()));
}
- InitSignatureCache();
- InitScriptExecutionCache();
+ ValidationCacheSizes validation_cache_sizes{};
+ ApplyArgsManOptions(args, validation_cache_sizes);
+ if (!InitSignatureCache(validation_cache_sizes.signature_cache_bytes)
+ || !InitScriptExecutionCache(validation_cache_sizes.script_execution_cache_bytes))
+ {
+ return InitError(strprintf(_("Unable to allocate memory for -maxsigcachesize: '%s' MiB"), args.GetIntArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_BYTES >> 20)));
+ }
int script_threads = args.GetIntArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
if (script_threads <= 0) {
@@ -1294,7 +1253,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
assert(!node.fee_estimator);
// Don't initialize fee estimation with old data if we don't relay transactions,
// as they would never get updated.
- if (!ignores_incoming_txs) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
+ if (!ignores_incoming_txs) node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(args));
// sanitize comments per BIP-0014, format user agent and check total size
std::vector<std::string> uacomments;
@@ -1326,6 +1285,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
if (!args.IsArgSet("-cjdnsreachable")) {
+ if (args.IsArgSet("-onlynet") && IsReachable(NET_CJDNS)) {
+ return InitError(
+ _("Outbound connections restricted to CJDNS (-onlynet=cjdns) but "
+ "-cjdnsreachable is not provided"));
+ }
SetReachable(NET_CJDNS, false);
}
// Now IsReachable(NET_CJDNS) is true if:
@@ -1333,6 +1297,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// 2.1. -onlynet is not given or
// 2.2. -onlynet=cjdns is given
+ // Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:
+ // If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip
+ // the DNS seeds by adjusting -dnsseed in InitParameterInteraction.
+ if (args.GetBoolArg("-dnsseed") == true && !IsReachable(NET_IPV4) && !IsReachable(NET_IPV6)) {
+ return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));
+ };
+
// Check for host lookup allowed before parsing any network related parameters
fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
@@ -1359,6 +1330,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
onion_proxy = addrProxy;
}
+ const bool onlynet_used_with_onion{args.IsArgSet("-onlynet") && IsReachable(NET_ONION)};
+
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
// -noonion (or -onion=0) disables connecting to .onion entirely
// An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none)
@@ -1366,6 +1339,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
if (onionArg != "") {
if (onionArg == "0") { // Handle -noonion/-onion=0
onion_proxy = Proxy{};
+ if (onlynet_used_with_onion) {
+ return InitError(
+ _("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
+ "reaching the Tor network is explicitly forbidden: -onion=0"));
+ }
} else {
CService addr;
if (!Lookup(onionArg, addr, 9050, fNameLookup) || !addr.IsValid()) {
@@ -1378,11 +1356,14 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
if (onion_proxy.IsValid()) {
SetProxy(NET_ONION, onion_proxy);
} else {
- if (args.IsArgSet("-onlynet") && IsReachable(NET_ONION)) {
+ // If -listenonion is set, then we will (try to) connect to the Tor control port
+ // later from the torcontrol thread and may retrieve the onion proxy from there.
+ const bool listenonion_disabled{!args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)};
+ if (onlynet_used_with_onion && listenonion_disabled) {
return InitError(
_("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
- "reaching the Tor network is not provided (no -proxy= and no -onion= given) or "
- "it is explicitly forbidden (-onion=0)"));
+ "reaching the Tor network is not provided: none of -proxy, -onion or "
+ "-listenonion is given"));
}
SetReachable(NET_ONION, false);
}
@@ -1411,7 +1392,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// cache size calculations
CacheSizes cache_sizes = CalculateCacheSizes(args, g_enabled_filter_types.size());
- int64_t nMempoolSizeMax = args.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
LogPrintf("Cache configuration:\n");
LogPrintf("* Using %.1f MiB for block index database\n", cache_sizes.block_tree_db * (1.0 / 1024 / 1024));
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
@@ -1422,128 +1402,83 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
cache_sizes.filter_index * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
}
LogPrintf("* Using %.1f MiB for chain state database\n", cache_sizes.coins_db * (1.0 / 1024 / 1024));
- LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", cache_sizes.coins * (1.0 / 1024 / 1024), nMempoolSizeMax * (1.0 / 1024 / 1024));
assert(!node.mempool);
assert(!node.chainman);
- const int mempool_check_ratio = std::clamp<int>(args.GetIntArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0, 1000000);
+
+ CTxMemPool::Options mempool_opts{
+ .estimator = node.fee_estimator.get(),
+ .check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
+ };
+ if (const auto err{ApplyArgsManOptions(args, chainparams, mempool_opts)}) {
+ return InitError(*err);
+ }
+ mempool_opts.check_ratio = std::clamp<int>(mempool_opts.check_ratio, 0, 1'000'000);
+
+ int64_t descendant_limit_bytes = mempool_opts.limits.descendant_size_vbytes * 40;
+ if (mempool_opts.max_size_bytes < 0 || mempool_opts.max_size_bytes < descendant_limit_bytes) {
+ return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(descendant_limit_bytes / 1'000'000.0)));
+ }
+ LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", cache_sizes.coins * (1.0 / 1024 / 1024), mempool_opts.max_size_bytes * (1.0 / 1024 / 1024));
for (bool fLoaded = false; !fLoaded && !ShutdownRequested();) {
- node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), mempool_check_ratio);
+ node.mempool = std::make_unique<CTxMemPool>(mempool_opts);
const ChainstateManager::Options chainman_opts{
- chainparams,
- GetAdjustedTime,
+ .chainparams = chainparams,
+ .adjusted_time_callback = GetAdjustedTime,
};
node.chainman = std::make_unique<ChainstateManager>(chainman_opts);
ChainstateManager& chainman = *node.chainman;
- const bool fReset = fReindex;
- bilingual_str strLoadError;
+ node::ChainstateLoadOptions options;
+ options.mempool = Assert(node.mempool.get());
+ options.reindex = node::fReindex;
+ options.reindex_chainstate = fReindexChainState;
+ options.prune = node::fPruneMode;
+ options.check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
+ options.check_level = args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
+ options.check_interrupt = ShutdownRequested;
+ options.coins_error_cb = [] {
+ uiInterface.ThreadSafeMessageBox(
+ _("Error reading from database, shutting down."),
+ "", CClientUIInterface::MSG_ERROR);
+ };
uiInterface.InitMessage(_("Loading block index…").translated);
- const int64_t load_block_index_start_time = GetTimeMillis();
- std::optional<ChainstateLoadingError> maybe_load_error;
- try {
- maybe_load_error = LoadChainstate(fReset,
- chainman,
- Assert(node.mempool.get()),
- fPruneMode,
- fReindexChainState,
- cache_sizes.block_tree_db,
- cache_sizes.coins_db,
- cache_sizes.coins,
- /*block_tree_db_in_memory=*/false,
- /*coins_db_in_memory=*/false,
- /*shutdown_requested=*/ShutdownRequested,
- /*coins_error_cb=*/[]() {
- uiInterface.ThreadSafeMessageBox(
- _("Error reading from database, shutting down."),
- "", CClientUIInterface::MSG_ERROR);
- });
- } catch (const std::exception& e) {
- LogPrintf("%s\n", e.what());
- maybe_load_error = ChainstateLoadingError::ERROR_GENERIC_BLOCKDB_OPEN_FAILED;
- }
- if (maybe_load_error.has_value()) {
- switch (maybe_load_error.value()) {
- case ChainstateLoadingError::ERROR_LOADING_BLOCK_DB:
- strLoadError = _("Error loading block database");
- break;
- case ChainstateLoadingError::ERROR_BAD_GENESIS_BLOCK:
- // If the loaded chain has a wrong genesis, bail out immediately
- // (we're likely using a testnet datadir, or the other way around).
- return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
- case ChainstateLoadingError::ERROR_PRUNED_NEEDS_REINDEX:
- strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain");
- break;
- case ChainstateLoadingError::ERROR_LOAD_GENESIS_BLOCK_FAILED:
- strLoadError = _("Error initializing block database");
- break;
- case ChainstateLoadingError::ERROR_CHAINSTATE_UPGRADE_FAILED:
- return InitError(_("Unsupported chainstate database format found. "
- "Please restart with -reindex-chainstate. This will "
- "rebuild the chainstate database."));
- case ChainstateLoadingError::ERROR_REPLAYBLOCKS_FAILED:
- strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.");
- break;
- case ChainstateLoadingError::ERROR_LOADCHAINTIP_FAILED:
- strLoadError = _("Error initializing block database");
- break;
- case ChainstateLoadingError::ERROR_GENERIC_BLOCKDB_OPEN_FAILED:
- strLoadError = _("Error opening block database");
- break;
- case ChainstateLoadingError::ERROR_BLOCKS_WITNESS_INSUFFICIENTLY_VALIDATED:
- strLoadError = strprintf(_("Witness data for blocks after height %d requires validation. Please restart with -reindex."),
- chainman.GetConsensus().SegwitHeight);
- break;
- case ChainstateLoadingError::SHUTDOWN_PROBED:
- break;
- }
- } else {
- std::optional<ChainstateLoadVerifyError> maybe_verify_error;
+ const auto load_block_index_start_time{SteadyClock::now()};
+ auto catch_exceptions = [](auto&& f) {
try {
- uiInterface.InitMessage(_("Verifying blocks…").translated);
- auto check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
- if (chainman.m_blockman.m_have_pruned && check_blocks > MIN_BLOCKS_TO_KEEP) {
- LogPrintfCategory(BCLog::PRUNE, "pruned datadir may not have more than %d blocks; only checking available blocks\n",
- MIN_BLOCKS_TO_KEEP);
- }
- maybe_verify_error = VerifyLoadedChainstate(chainman,
- fReset,
- fReindexChainState,
- check_blocks,
- args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL));
+ return f();
} catch (const std::exception& e) {
LogPrintf("%s\n", e.what());
- maybe_verify_error = ChainstateLoadVerifyError::ERROR_GENERIC_FAILURE;
+ return std::make_tuple(node::ChainstateLoadStatus::FAILURE, _("Error opening block database"));
}
- if (maybe_verify_error.has_value()) {
- switch (maybe_verify_error.value()) {
- case ChainstateLoadVerifyError::ERROR_BLOCK_FROM_FUTURE:
- strLoadError = _("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");
- break;
- case ChainstateLoadVerifyError::ERROR_CORRUPTED_BLOCK_DB:
- strLoadError = _("Corrupted block database detected");
- break;
- case ChainstateLoadVerifyError::ERROR_GENERIC_FAILURE:
- strLoadError = _("Error opening block database");
- break;
- }
- } else {
+ };
+ auto [status, error] = catch_exceptions([&]{ return LoadChainstate(chainman, cache_sizes, options); });
+ if (status == node::ChainstateLoadStatus::SUCCESS) {
+ uiInterface.InitMessage(_("Verifying blocks…").translated);
+ if (chainman.m_blockman.m_have_pruned && options.check_blocks > MIN_BLOCKS_TO_KEEP) {
+ LogPrintfCategory(BCLog::PRUNE, "pruned datadir may not have more than %d blocks; only checking available blocks\n",
+ MIN_BLOCKS_TO_KEEP);
+ }
+ std::tie(status, error) = catch_exceptions([&]{ return VerifyLoadedChainstate(chainman, options);});
+ if (status == node::ChainstateLoadStatus::SUCCESS) {
fLoaded = true;
- LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time);
+ LogPrintf(" block index %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - load_block_index_start_time));
}
}
+ if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB) {
+ return InitError(error);
+ }
+
if (!fLoaded && !ShutdownRequested()) {
// first suggest a reindex
- if (!fReset) {
+ if (!options.reindex) {
bool fRet = uiInterface.ThreadSafeQuestion(
- strLoadError + Untranslated(".\n\n") + _("Do you want to rebuild the block database now?"),
- strLoadError.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.",
+ error + Untranslated(".\n\n") + _("Do you want to rebuild the block database now?"),
+ error.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.",
"", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
if (fRet) {
fReindex = true;
@@ -1553,7 +1488,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
return false;
}
} else {
- return InitError(strLoadError);
+ return InitError(error);
}
}
}
@@ -1579,22 +1514,22 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
return InitError(*error);
}
- g_txindex = std::make_unique<TxIndex>(cache_sizes.tx_index, false, fReindex);
- if (!g_txindex->Start(chainman.ActiveChainstate())) {
+ g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), cache_sizes.tx_index, false, fReindex);
+ if (!g_txindex->Start()) {
return false;
}
}
for (const auto& filter_type : g_enabled_filter_types) {
- InitBlockFilterIndex(filter_type, cache_sizes.filter_index, false, fReindex);
- if (!GetBlockFilterIndex(filter_type)->Start(chainman.ActiveChainstate())) {
+ InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, cache_sizes.filter_index, false, fReindex);
+ if (!GetBlockFilterIndex(filter_type)->Start()) {
return false;
}
}
if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
- g_coin_stats_index = std::make_unique<CoinStatsIndex>(/* cache size */ 0, false, fReindex);
- if (!g_coin_stats_index->Start(chainman.ActiveChainstate())) {
+ g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /* cache size */ 0, false, fReindex);
+ if (!g_coin_stats_index->Start()) {
return false;
}
}
@@ -1608,18 +1543,19 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// ********************************************************* Step 10: data directory maintenance
- // if pruning, unset the service bit and perform the initial blockstore prune
+ // if pruning, perform the initial blockstore prune
// after any wallet rescanning has taken place.
if (fPruneMode) {
- LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
- nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
if (!fReindex) {
LOCK(cs_main);
- for (CChainState* chainstate : chainman.GetAll()) {
+ for (Chainstate* chainstate : chainman.GetAll()) {
uiInterface.InitMessage(_("Pruning blockstore…").translated);
chainstate->PruneAndFlush();
}
}
+ } else {
+ LogPrintf("Setting NODE_NETWORK on non-prune mode\n");
+ nLocalServices = ServiceFlags(nLocalServices | NODE_NETWORK);
}
// ********************************************************* Step 11: import blocks
@@ -1636,7 +1572,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
// No locking, as this happens before any background thread is started.
boost::signals2::connection block_notify_genesis_wait_connection;
- if (chainman.ActiveChain().Tip() == nullptr) {
+ if (WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip() == nullptr)) {
block_notify_genesis_wait_connection = uiInterface.NotifyBlockTip_connect(std::bind(BlockNotifyGenesisWait, std::placeholders::_2));
} else {
fHaveGenesis = true;
@@ -1661,7 +1597,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
chainman.m_load_block = std::thread(&util::TraceThread, "loadblk", [=, &chainman, &args] {
- ThreadImport(chainman, vImportFiles, args);
+ ThreadImport(chainman, vImportFiles, args, ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{});
});
// Wait for genesis block to be processed
@@ -1826,6 +1762,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
SetProxy(NET_I2P, Proxy{addr});
} else {
+ if (args.IsArgSet("-onlynet") && IsReachable(NET_I2P)) {
+ return InitError(
+ _("Outbound connections restricted to i2p (-onlynet=i2p) but "
+ "-i2psam is not provided"));
+ }
SetReachable(NET_I2P, false);
}
@@ -1840,12 +1781,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// At this point, the RPC is "started", but still in warmup, which means it
// cannot yet be called. Before we make it callable, we need to make sure
// that the RPC's view of the best block is valid and consistent with
- // ChainstateManager's ActiveTip.
+ // ChainstateManager's active tip.
//
// If we do not do this, RPC's view of the best block will be height=0 and
// hash=0x0. This will lead to erroroneous responses for things like
// waitforblockheight.
- RPCNotifyBlockChange(chainman.ActiveTip());
+ RPCNotifyBlockChange(WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip()));
SetRPCWarmupFinished();
uiInterface.InitMessage(_("Done loading").translated);
diff --git a/src/init/common.cpp b/src/init/common.cpp
index a0cdf44f47..f2d2c5640a 100644
--- a/src/init/common.cpp
+++ b/src/init/common.cpp
@@ -11,6 +11,7 @@
#include <logging.h>
#include <node/interface_ui.h>
#include <tinyformat.h>
+#include <util/string.h>
#include <util/system.h>
#include <util/time.h>
#include <util/translation.h>
@@ -23,11 +24,12 @@ namespace init {
void AddLoggingArgs(ArgsManager& argsman)
{
argsman.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (-nodebuglogfile to disable; default: %s)", DEFAULT_DEBUGLOGFILE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
- argsman.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). "
- "If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + LogInstance().LogCategoriesString() + ". This option can be specified multiple times to output multiple categories.",
+ argsman.AddArg("-debug=<category>", "Output debug and trace logging (default: -nodebug, supplying <category> is optional). "
+ "If <category> is not supplied or if <category> = 1, output all debug and trace logging. <category> can be: " + LogInstance().LogCategoriesString() + ". This option can be specified multiple times to output multiple categories.",
ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-debugexclude=<category>", "Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except the specified category. This option can be specified multiple times to exclude multiple categories.", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-debugexclude=<category>", "Exclude debug and trace logging for a category. Can be used in conjunction with -debug=1 to output debug and trace logging for all categories except the specified category. This option can be specified multiple times to exclude multiple categories.", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-loglevel=<level>|<category>:<level>", strprintf("Set the global or per-category severity level for logging categories enabled with the -debug configuration option or the logging RPC: %s (default=%s); warning and error levels are always logged. If <category>:<level> is supplied, the setting will override the global one and may be specified multiple times to set multiple category-specific levels. <category> can be: %s.", LogInstance().LogLevelsString(), LogInstance().LogLevelToStr(BCLog::DEFAULT_LOG_LEVEL), LogInstance().LogCategoriesString()), ArgsManager::DISALLOW_NEGATION | ArgsManager::DISALLOW_ELISION | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#ifdef HAVE_THREAD_LOCAL
argsman.AddArg("-logthreadnames", strprintf("Prepend debug output with name of the originating thread (only available on platforms supporting thread_local) (default: %u)", DEFAULT_LOGTHREADNAMES), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
@@ -55,6 +57,26 @@ void SetLoggingOptions(const ArgsManager& args)
fLogIPs = args.GetBoolArg("-logips", DEFAULT_LOGIPS);
}
+void SetLoggingLevel(const ArgsManager& args)
+{
+ if (args.IsArgSet("-loglevel")) {
+ for (const std::string& level_str : args.GetArgs("-loglevel")) {
+ if (level_str.find_first_of(':', 3) == std::string::npos) {
+ // user passed a global log level, i.e. -loglevel=<level>
+ if (!LogInstance().SetLogLevel(level_str)) {
+ InitWarning(strprintf(_("Unsupported global logging level -loglevel=%s. Valid values: %s."), level_str, LogInstance().LogLevelsString()));
+ }
+ } else {
+ // user passed a category-specific log level, i.e. -loglevel=<category>:<level>
+ const auto& toks = SplitString(level_str, ':');
+ if (!(toks.size() == 2 && LogInstance().SetCategoryLogLevel(toks[0], toks[1]))) {
+ InitWarning(strprintf(_("Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=<category>:<loglevel>. Valid categories: %s. Valid loglevels: %s."), level_str, LogInstance().LogCategoriesString(), LogInstance().LogLevelsString()));
+ }
+ }
+ }
+ }
+}
+
void SetLoggingCategories(const ArgsManager& args)
{
if (args.IsArgSet("-debug")) {
@@ -99,7 +121,7 @@ bool StartLogging(const ArgsManager& args)
LogPrintf("Using data directory %s\n", fs::PathToString(gArgs.GetDataDirNet()));
// Only log conf file usage message if conf file actually exists.
- fs::path config_file_path = GetConfigFile(args.GetArg("-conf", BITCOIN_CONF_FILENAME));
+ fs::path config_file_path = GetConfigFile(args.GetPathArg("-conf", BITCOIN_CONF_FILENAME));
if (fs::exists(config_file_path)) {
LogPrintf("Config file: %s\n", fs::PathToString(config_file_path));
} else if (args.IsArgSet("-conf")) {
diff --git a/src/init/common.h b/src/init/common.h
index 2c7f485908..53c860c297 100644
--- a/src/init/common.h
+++ b/src/init/common.h
@@ -14,6 +14,7 @@ namespace init {
void AddLoggingArgs(ArgsManager& args);
void SetLoggingOptions(const ArgsManager& args);
void SetLoggingCategories(const ArgsManager& args);
+void SetLoggingLevel(const ArgsManager& args);
bool StartLogging(const ArgsManager& args);
void LogPackageVersion();
} // namespace init
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index ddfb4bda95..5fc0e540a9 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -18,6 +18,7 @@
class ArgsManager;
class CBlock;
+class CBlockUndo;
class CFeeRate;
class CRPCCommand;
class CScheduler;
@@ -37,6 +38,12 @@ namespace interfaces {
class Handler;
class Wallet;
+//! Hash/height pair to help track and identify blocks.
+struct BlockKey {
+ uint256 hash;
+ int height = -1;
+};
+
//! Helper for findBlock to selectively return pieces of block data. If block is
//! found, data will be returned by setting specified output variables. If block
//! is not found, output variables will keep their previous values.
@@ -50,6 +57,8 @@ public:
FoundBlock& mtpTime(int64_t& mtp_time) { m_mtp_time = &mtp_time; return *this; }
//! Return whether block is in the active (most-work) chain.
FoundBlock& inActiveChain(bool& in_active_chain) { m_in_active_chain = &in_active_chain; return *this; }
+ //! Return locator if block is in the active chain.
+ FoundBlock& locator(CBlockLocator& locator) { m_locator = &locator; return *this; }
//! Return next block in the active chain if current block is in the active chain.
FoundBlock& nextBlock(const FoundBlock& next_block) { m_next_block = &next_block; return *this; }
//! Read block data from disk. If the block exists but doesn't have data
@@ -62,11 +71,25 @@ public:
int64_t* m_max_time = nullptr;
int64_t* m_mtp_time = nullptr;
bool* m_in_active_chain = nullptr;
+ CBlockLocator* m_locator = nullptr;
const FoundBlock* m_next_block = nullptr;
CBlock* m_data = nullptr;
mutable bool found = false;
};
+//! Block data sent with blockConnected, blockDisconnected notifications.
+struct BlockInfo {
+ const uint256& hash;
+ const uint256* prev_hash = nullptr;
+ int height = -1;
+ int file_number = -1;
+ unsigned data_pos = 0;
+ const CBlock* data = nullptr;
+ const CBlockUndo* undo_data = nullptr;
+
+ BlockInfo(const uint256& hash LIFETIMEBOUND) : hash(hash) {}
+};
+
//! Interface giving clients (wallet processes, maybe other analysis tools in
//! the future) ability to access to the chain state, receive notifications,
//! estimate fees, and submit transactions.
@@ -111,6 +134,10 @@ public:
//! Get locator for the current chain tip.
virtual CBlockLocator getTipLocator() = 0;
+ //! Return a locator that refers to a block in the active chain.
+ //! If specified block is not in the active chain, return locator for the latest ancestor that is in the chain.
+ virtual CBlockLocator getActiveChainLocator(const uint256& block_hash) = 0;
+
//! Return height of the highest block on chain in common with the locator,
//! which will either be the original block used to create the locator,
//! or one of its ancestors.
@@ -235,8 +262,8 @@ public:
virtual ~Notifications() {}
virtual void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) {}
virtual void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) {}
- virtual void blockConnected(const CBlock& block, int height) {}
- virtual void blockDisconnected(const CBlock& block, int height) {}
+ virtual void blockConnected(const BlockInfo& block) {}
+ virtual void blockDisconnected(const BlockInfo& block) {}
virtual void updatedBlockTip() {}
virtual void chainStateFlushed(const CBlockLocator& locator) {}
};
@@ -283,6 +310,13 @@ public:
//! to be prepared to handle this by ignoring notifications about unknown
//! removed transactions and already added new transactions.
virtual void requestMempoolTransactions(Notifications& notifications) = 0;
+
+ //! Return true if an assumed-valid chain is in use.
+ virtual bool hasAssumedValidChain() = 0;
+
+ //! Get internal node context. Useful for testing, but not
+ //! accessible across processes.
+ virtual node::NodeContext* context() { return nullptr; }
};
//! Interface to let node manage chain clients (wallets, or maybe tools for
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 2c31e12ada..dbdb21eb91 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -260,7 +260,7 @@ public:
//! Register handler for header tip messages.
using NotifyHeaderTipFn =
- std::function<void(SynchronizationState, interfaces::BlockTip tip, double verification_progress)>;
+ std::function<void(SynchronizationState, interfaces::BlockTip tip, bool presync)>;
virtual std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) = 0;
//! Get and set internal node context. Useful for testing, but not
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index f26ac866dc..1148dc7e4c 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -12,6 +12,7 @@
#include <script/standard.h> // For CTxDestination
#include <support/allocators/secure.h> // For SecureString
#include <util/message.h>
+#include <util/result.h>
#include <util/ui_change_type.h>
#include <cstdint>
@@ -87,7 +88,7 @@ public:
virtual std::string getWalletName() = 0;
// Get a new address.
- virtual bool getNewDestination(const OutputType type, const std::string label, CTxDestination& dest) = 0;
+ virtual util::Result<CTxDestination> getNewDestination(const OutputType type, const std::string& label) = 0;
//! Get public key.
virtual bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) = 0;
@@ -114,7 +115,7 @@ public:
std::string* purpose) = 0;
//! Get wallet address list.
- virtual std::vector<WalletAddress> getAddresses() = 0;
+ virtual std::vector<WalletAddress> getAddresses() const = 0;
//! Get receive requests.
virtual std::vector<std::string> getAddressReceiveRequests() = 0;
@@ -138,12 +139,11 @@ public:
virtual void listLockedCoins(std::vector<COutPoint>& outputs) = 0;
//! Create transaction.
- virtual CTransactionRef createTransaction(const std::vector<wallet::CRecipient>& recipients,
+ virtual util::Result<CTransactionRef> createTransaction(const std::vector<wallet::CRecipient>& recipients,
const wallet::CCoinControl& coin_control,
bool sign,
int& change_pos,
- CAmount& fee,
- bilingual_str& fail_reason) = 0;
+ CAmount& fee) = 0;
//! Commit transaction.
virtual void commitTransaction(CTransactionRef tx,
@@ -183,7 +183,7 @@ public:
virtual WalletTx getWalletTx(const uint256& txid) = 0;
//! Get list of all wallet transactions.
- virtual std::vector<WalletTx> getWalletTxs() = 0;
+ virtual std::set<WalletTx> getWalletTxs() = 0;
//! Try to get updated status for a particular transaction, if possible without blocking.
virtual bool tryGetTxStatus(const uint256& txid,
@@ -320,31 +320,31 @@ class WalletLoader : public ChainClient
{
public:
//! Create new wallet.
- virtual std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
+ virtual util::Result<std::unique_ptr<Wallet>> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, std::vector<bilingual_str>& warnings) = 0;
- //! Load existing wallet.
- virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
+ //! Load existing wallet.
+ virtual util::Result<std::unique_ptr<Wallet>> loadWallet(const std::string& name, std::vector<bilingual_str>& warnings) = 0;
- //! Return default wallet directory.
- virtual std::string getWalletDir() = 0;
+ //! Return default wallet directory.
+ virtual std::string getWalletDir() = 0;
- //! Restore backup wallet
- virtual std::unique_ptr<Wallet> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
+ //! Restore backup wallet
+ virtual util::Result<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) = 0;
- //! Return available wallets in wallet directory.
- virtual std::vector<std::string> listWalletDir() = 0;
+ //! Return available wallets in wallet directory.
+ virtual std::vector<std::string> listWalletDir() = 0;
- //! Return interfaces for accessing wallets (if any).
- virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
+ //! Return interfaces for accessing wallets (if any).
+ virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
- //! Register handler for load wallet messages. This callback is triggered by
- //! createWallet and loadWallet above, and also triggered when wallets are
- //! loaded at startup or by RPC.
- using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
- virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
+ //! Register handler for load wallet messages. This callback is triggered by
+ //! createWallet and loadWallet above, and also triggered when wallets are
+ //! loaded at startup or by RPC.
+ using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
+ virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
- //! Return pointer to internal context, useful for testing.
- virtual wallet::WalletContext* context() { return nullptr; }
+ //! Return pointer to internal context, useful for testing.
+ virtual wallet::WalletContext* context() { return nullptr; }
};
//! Information about one wallet address.
@@ -395,6 +395,8 @@ struct WalletTx
int64_t time;
std::map<std::string, std::string> value_map;
bool is_coinbase;
+
+ bool operator<(const WalletTx& a) const { return tx->GetHash() < a.tx->GetHash(); }
};
//! Updated transaction status.
diff --git a/src/kernel/chain.cpp b/src/kernel/chain.cpp
new file mode 100644
index 0000000000..82e77125d7
--- /dev/null
+++ b/src/kernel/chain.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chain.h>
+#include <interfaces/chain.h>
+#include <sync.h>
+#include <uint256.h>
+
+class CBlock;
+
+namespace kernel {
+interfaces::BlockInfo MakeBlockInfo(const CBlockIndex* index, const CBlock* data)
+{
+ interfaces::BlockInfo info{index ? *index->phashBlock : uint256::ZERO};
+ if (index) {
+ info.prev_hash = index->pprev ? index->pprev->phashBlock : nullptr;
+ info.height = index->nHeight;
+ LOCK(::cs_main);
+ info.file_number = index->nFile;
+ info.data_pos = index->nDataPos;
+ }
+ info.data = data;
+ return info;
+}
+} // namespace kernel
diff --git a/src/kernel/chain.h b/src/kernel/chain.h
new file mode 100644
index 0000000000..f0750f8266
--- /dev/null
+++ b/src/kernel/chain.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_KERNEL_CHAIN_H
+#define BITCOIN_KERNEL_CHAIN_H
+
+class CBlock;
+class CBlockIndex;
+namespace interfaces {
+struct BlockInfo;
+} // namespace interfaces
+
+namespace kernel {
+//! Return data from block index.
+interfaces::BlockInfo MakeBlockInfo(const CBlockIndex* block_index, const CBlock* data = nullptr);
+} // namespace kernel
+
+#endif // BITCOIN_KERNEL_CHAIN_H
diff --git a/src/kernel/chainstatemanager_opts.h b/src/kernel/chainstatemanager_opts.h
index 575d94e2e9..520d0e8e75 100644
--- a/src/kernel/chainstatemanager_opts.h
+++ b/src/kernel/chainstatemanager_opts.h
@@ -5,11 +5,15 @@
#ifndef BITCOIN_KERNEL_CHAINSTATEMANAGER_OPTS_H
#define BITCOIN_KERNEL_CHAINSTATEMANAGER_OPTS_H
+#include <util/time.h>
+
#include <cstdint>
#include <functional>
class CChainParams;
+namespace kernel {
+
/**
* An options struct for `ChainstateManager`, more ergonomically referred to as
* `ChainstateManager::Options` due to the using-declaration in
@@ -17,7 +21,9 @@ class CChainParams;
*/
struct ChainstateManagerOpts {
const CChainParams& chainparams;
- const std::function<int64_t()> adjusted_time_callback{nullptr};
+ const std::function<NodeClock::time_point()> adjusted_time_callback{nullptr};
};
+} // namespace kernel
+
#endif // BITCOIN_KERNEL_CHAINSTATEMANAGER_OPTS_H
diff --git a/src/kernel/checks.cpp b/src/kernel/checks.cpp
index 2a1dd3bfa2..4c303c172c 100644
--- a/src/kernel/checks.cpp
+++ b/src/kernel/checks.cpp
@@ -7,21 +7,24 @@
#include <key.h>
#include <random.h>
#include <util/time.h>
+#include <util/translation.h>
+
+#include <memory>
namespace kernel {
-std::optional<SanityCheckError> SanityChecks(const Context&)
+std::optional<bilingual_str> SanityChecks(const Context&)
{
if (!ECC_InitSanityCheck()) {
- return SanityCheckError::ERROR_ECC;
+ return Untranslated("Elliptic curve cryptography sanity check failure. Aborting.");
}
if (!Random_SanityCheck()) {
- return SanityCheckError::ERROR_RANDOM;
+ return Untranslated("OS cryptographic RNG sanity check failure. Aborting.");
}
if (!ChronoSanityCheck()) {
- return SanityCheckError::ERROR_CHRONO;
+ return Untranslated("Clock epoch mismatch. Aborting.");
}
return std::nullopt;
diff --git a/src/kernel/checks.h b/src/kernel/checks.h
index 80b207f607..3eb14824fb 100644
--- a/src/kernel/checks.h
+++ b/src/kernel/checks.h
@@ -7,20 +7,16 @@
#include <optional>
+struct bilingual_str;
+
namespace kernel {
struct Context;
-enum class SanityCheckError {
- ERROR_ECC,
- ERROR_RANDOM,
- ERROR_CHRONO,
-};
-
/**
* Ensure a usable environment with all necessary library support.
*/
-std::optional<SanityCheckError> SanityChecks(const Context&);
+std::optional<bilingual_str> SanityChecks(const Context&);
}
diff --git a/src/kernel/coinstats.cpp b/src/kernel/coinstats.cpp
index f380871627..06a4b8c974 100644
--- a/src/kernel/coinstats.cpp
+++ b/src/kernel/coinstats.cpp
@@ -4,16 +4,32 @@
#include <kernel/coinstats.h>
+#include <chain.h>
#include <coins.h>
#include <crypto/muhash.h>
#include <hash.h>
+#include <node/blockstorage.h>
+#include <primitives/transaction.h>
+#include <script/script.h>
#include <serialize.h>
+#include <span.h>
+#include <streams.h>
+#include <sync.h>
+#include <tinyformat.h>
#include <uint256.h>
+#include <util/check.h>
#include <util/overflow.h>
#include <util/system.h>
#include <validation.h>
+#include <version.h>
+#include <cassert>
+#include <iosfwd>
+#include <iterator>
#include <map>
+#include <memory>
+#include <string>
+#include <utility>
namespace kernel {
@@ -52,7 +68,7 @@ CDataStream TxOutSer(const COutPoint& outpoint, const Coin& coin) {
//! It is also possible, though very unlikely, that a change in this
//! construction could cause a previously invalid (and potentially malicious)
//! UTXO snapshot to be considered valid.
-static void ApplyHash(CHashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
+static void ApplyHash(HashWriter& ss, const uint256& hash, const std::map<uint32_t, Coin>& outputs)
{
for (auto it = outputs.begin(); it != outputs.end(); ++it) {
if (it == outputs.begin()) {
@@ -143,7 +159,7 @@ std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsV
bool success = [&]() -> bool {
switch (hash_type) {
case(CoinStatsHashType::HASH_SERIALIZED): {
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
+ HashWriter ss{};
return ComputeUTXOStats(view, stats, ss, interruption_point);
}
case(CoinStatsHashType::MUHASH): {
@@ -164,7 +180,7 @@ std::optional<CCoinsStats> ComputeUTXOStats(CoinStatsHashType hash_type, CCoinsV
}
// The legacy hash serializes the hashBlock
-static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
+static void PrepareHash(HashWriter& ss, const CCoinsStats& stats)
{
ss << stats.hashBlock;
}
@@ -172,7 +188,7 @@ static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
static void PrepareHash(MuHash3072& muhash, CCoinsStats& stats) {}
static void PrepareHash(std::nullptr_t, CCoinsStats& stats) {}
-static void FinalizeHash(CHashWriter& ss, CCoinsStats& stats)
+static void FinalizeHash(HashWriter& ss, CCoinsStats& stats)
{
stats.hashSerialized = ss.GetHash();
}
diff --git a/src/kernel/coinstats.h b/src/kernel/coinstats.h
index a15957233f..b7c1328e93 100644
--- a/src/kernel/coinstats.h
+++ b/src/kernel/coinstats.h
@@ -5,16 +5,18 @@
#ifndef BITCOIN_KERNEL_COINSTATS_H
#define BITCOIN_KERNEL_COINSTATS_H
-#include <chain.h>
-#include <coins.h>
#include <consensus/amount.h>
#include <streams.h>
#include <uint256.h>
#include <cstdint>
#include <functional>
+#include <optional>
class CCoinsView;
+class Coin;
+class COutPoint;
+class CScript;
namespace node {
class BlockManager;
} // namespace node
diff --git a/src/kernel/mempool_limits.h b/src/kernel/mempool_limits.h
new file mode 100644
index 0000000000..e192e7e6cd
--- /dev/null
+++ b/src/kernel/mempool_limits.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_KERNEL_MEMPOOL_LIMITS_H
+#define BITCOIN_KERNEL_MEMPOOL_LIMITS_H
+
+#include <policy/policy.h>
+
+#include <cstdint>
+
+namespace kernel {
+/**
+ * Options struct containing limit options for a CTxMemPool. Default constructor
+ * populates the struct with sane default values which can be modified.
+ *
+ * Most of the time, this struct should be referenced as CTxMemPool::Limits.
+ */
+struct MemPoolLimits {
+ //! The maximum allowed number of transactions in a package including the entry and its ancestors.
+ int64_t ancestor_count{DEFAULT_ANCESTOR_LIMIT};
+ //! The maximum allowed size in virtual bytes of an entry and its ancestors within a package.
+ int64_t ancestor_size_vbytes{DEFAULT_ANCESTOR_SIZE_LIMIT_KVB * 1'000};
+ //! The maximum allowed number of transactions in a package including the entry and its descendants.
+ int64_t descendant_count{DEFAULT_DESCENDANT_LIMIT};
+ //! The maximum allowed size in virtual bytes of an entry and its descendants within a package.
+ int64_t descendant_size_vbytes{DEFAULT_DESCENDANT_SIZE_LIMIT_KVB * 1'000};
+};
+} // namespace kernel
+
+#endif // BITCOIN_KERNEL_MEMPOOL_LIMITS_H
diff --git a/src/kernel/mempool_options.h b/src/kernel/mempool_options.h
new file mode 100644
index 0000000000..dad6f14c39
--- /dev/null
+++ b/src/kernel/mempool_options.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_KERNEL_MEMPOOL_OPTIONS_H
+#define BITCOIN_KERNEL_MEMPOOL_OPTIONS_H
+
+#include <kernel/mempool_limits.h>
+
+#include <policy/feerate.h>
+#include <policy/policy.h>
+#include <script/standard.h>
+
+#include <chrono>
+#include <cstdint>
+#include <optional>
+
+class CBlockPolicyEstimator;
+
+/** Default for -maxmempool, maximum megabytes of mempool memory usage */
+static constexpr unsigned int DEFAULT_MAX_MEMPOOL_SIZE_MB{300};
+/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
+static constexpr unsigned int DEFAULT_MEMPOOL_EXPIRY_HOURS{336};
+/** Default for -mempoolfullrbf, if the transaction replaceability signaling is ignored */
+static constexpr bool DEFAULT_MEMPOOL_FULL_RBF{false};
+
+namespace kernel {
+/**
+ * Options struct containing options for constructing a CTxMemPool. Default
+ * constructor populates the struct with sane default values which can be
+ * modified.
+ *
+ * Most of the time, this struct should be referenced as CTxMemPool::Options.
+ */
+struct MemPoolOptions {
+ /* Used to estimate appropriate transaction fees. */
+ CBlockPolicyEstimator* estimator{nullptr};
+ /* The ratio used to determine how often sanity checks will run. */
+ int check_ratio{0};
+ int64_t max_size_bytes{DEFAULT_MAX_MEMPOOL_SIZE_MB * 1'000'000};
+ std::chrono::seconds expiry{std::chrono::hours{DEFAULT_MEMPOOL_EXPIRY_HOURS}};
+ CFeeRate incremental_relay_feerate{DEFAULT_INCREMENTAL_RELAY_FEE};
+ /** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
+ CFeeRate min_relay_feerate{DEFAULT_MIN_RELAY_TX_FEE};
+ CFeeRate dust_relay_feerate{DUST_RELAY_TX_FEE};
+ /**
+ * A data carrying output is an unspendable output containing data. The script
+ * type is designated as TxoutType::NULL_DATA.
+ *
+ * Maximum size of TxoutType::NULL_DATA scripts that this node considers standard.
+ * If nullopt, any size is nonstandard.
+ */
+ std::optional<unsigned> max_datacarrier_bytes{DEFAULT_ACCEPT_DATACARRIER ? std::optional{MAX_OP_RETURN_RELAY} : std::nullopt};
+ bool permit_bare_multisig{DEFAULT_PERMIT_BAREMULTISIG};
+ bool require_standard{true};
+ bool full_rbf{DEFAULT_MEMPOOL_FULL_RBF};
+ MemPoolLimits limits{};
+};
+} // namespace kernel
+
+#endif // BITCOIN_KERNEL_MEMPOOL_OPTIONS_H
diff --git a/src/kernel/mempool_persist.cpp b/src/kernel/mempool_persist.cpp
new file mode 100644
index 0000000000..a14b2e6163
--- /dev/null
+++ b/src/kernel/mempool_persist.cpp
@@ -0,0 +1,189 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <kernel/mempool_persist.h>
+
+#include <clientversion.h>
+#include <consensus/amount.h>
+#include <fs.h>
+#include <logging.h>
+#include <primitives/transaction.h>
+#include <serialize.h>
+#include <shutdown.h>
+#include <streams.h>
+#include <sync.h>
+#include <txmempool.h>
+#include <uint256.h>
+#include <util/system.h>
+#include <util/time.h>
+#include <validation.h>
+
+#include <chrono>
+#include <cstdint>
+#include <cstdio>
+#include <exception>
+#include <functional>
+#include <map>
+#include <memory>
+#include <set>
+#include <stdexcept>
+#include <utility>
+#include <vector>
+
+using fsbridge::FopenFn;
+
+namespace kernel {
+
+static const uint64_t MEMPOOL_DUMP_VERSION = 1;
+
+bool LoadMempool(CTxMemPool& pool, const fs::path& load_path, Chainstate& active_chainstate, FopenFn mockable_fopen_function)
+{
+ if (load_path.empty()) return false;
+
+ FILE* filestr{mockable_fopen_function(load_path, "rb")};
+ CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
+ if (file.IsNull()) {
+ LogPrintf("Failed to open mempool file from disk. Continuing anyway.\n");
+ return false;
+ }
+
+ int64_t count = 0;
+ int64_t expired = 0;
+ int64_t failed = 0;
+ int64_t already_there = 0;
+ int64_t unbroadcast = 0;
+ auto now = NodeClock::now();
+
+ try {
+ uint64_t version;
+ file >> version;
+ if (version != MEMPOOL_DUMP_VERSION) {
+ return false;
+ }
+ uint64_t num;
+ file >> num;
+ while (num) {
+ --num;
+ CTransactionRef tx;
+ int64_t nTime;
+ int64_t nFeeDelta;
+ file >> tx;
+ file >> nTime;
+ file >> nFeeDelta;
+
+ CAmount amountdelta = nFeeDelta;
+ if (amountdelta) {
+ pool.PrioritiseTransaction(tx->GetHash(), amountdelta);
+ }
+ if (nTime > TicksSinceEpoch<std::chrono::seconds>(now - pool.m_expiry)) {
+ LOCK(cs_main);
+ const auto& accepted = AcceptToMemoryPool(active_chainstate, tx, nTime, /*bypass_limits=*/false, /*test_accept=*/false);
+ if (accepted.m_result_type == MempoolAcceptResult::ResultType::VALID) {
+ ++count;
+ } else {
+ // mempool may contain the transaction already, e.g. from
+ // wallet(s) having loaded it while we were processing
+ // mempool transactions; consider these as valid, instead of
+ // failed, but mark them as 'already there'
+ if (pool.exists(GenTxid::Txid(tx->GetHash()))) {
+ ++already_there;
+ } else {
+ ++failed;
+ }
+ }
+ } else {
+ ++expired;
+ }
+ if (ShutdownRequested())
+ return false;
+ }
+ std::map<uint256, CAmount> mapDeltas;
+ file >> mapDeltas;
+
+ for (const auto& i : mapDeltas) {
+ pool.PrioritiseTransaction(i.first, i.second);
+ }
+
+ std::set<uint256> unbroadcast_txids;
+ file >> unbroadcast_txids;
+ unbroadcast = unbroadcast_txids.size();
+ for (const auto& txid : unbroadcast_txids) {
+ // Ensure transactions were accepted to mempool then add to
+ // unbroadcast set.
+ if (pool.get(txid) != nullptr) pool.AddUnbroadcastTx(txid);
+ }
+ } catch (const std::exception& e) {
+ LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
+ return false;
+ }
+
+ LogPrintf("Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there, %i waiting for initial broadcast\n", count, failed, expired, already_there, unbroadcast);
+ return true;
+}
+
+bool DumpMempool(const CTxMemPool& pool, const fs::path& dump_path, FopenFn mockable_fopen_function, bool skip_file_commit)
+{
+ auto start = SteadyClock::now();
+
+ std::map<uint256, CAmount> mapDeltas;
+ std::vector<TxMempoolInfo> vinfo;
+ std::set<uint256> unbroadcast_txids;
+
+ static Mutex dump_mutex;
+ LOCK(dump_mutex);
+
+ {
+ LOCK(pool.cs);
+ for (const auto &i : pool.mapDeltas) {
+ mapDeltas[i.first] = i.second;
+ }
+ vinfo = pool.infoAll();
+ unbroadcast_txids = pool.GetUnbroadcastTxs();
+ }
+
+ auto mid = SteadyClock::now();
+
+ try {
+ FILE* filestr{mockable_fopen_function(dump_path + ".new", "wb")};
+ if (!filestr) {
+ return false;
+ }
+
+ CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
+
+ uint64_t version = MEMPOOL_DUMP_VERSION;
+ file << version;
+
+ file << (uint64_t)vinfo.size();
+ for (const auto& i : vinfo) {
+ file << *(i.tx);
+ file << int64_t{count_seconds(i.m_time)};
+ file << int64_t{i.nFeeDelta};
+ mapDeltas.erase(i.tx->GetHash());
+ }
+
+ file << mapDeltas;
+
+ LogPrintf("Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
+ file << unbroadcast_txids;
+
+ if (!skip_file_commit && !FileCommit(file.Get()))
+ throw std::runtime_error("FileCommit failed");
+ file.fclose();
+ if (!RenameOver(dump_path + ".new", dump_path)) {
+ throw std::runtime_error("Rename failed");
+ }
+ auto last = SteadyClock::now();
+
+ LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n",
+ Ticks<SecondsDouble>(mid - start),
+ Ticks<SecondsDouble>(last - mid));
+ } catch (const std::exception& e) {
+ LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what());
+ return false;
+ }
+ return true;
+}
+
+} // namespace kernel
diff --git a/src/kernel/mempool_persist.h b/src/kernel/mempool_persist.h
new file mode 100644
index 0000000000..ca4917e38b
--- /dev/null
+++ b/src/kernel/mempool_persist.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_KERNEL_MEMPOOL_PERSIST_H
+#define BITCOIN_KERNEL_MEMPOOL_PERSIST_H
+
+#include <fs.h>
+
+class Chainstate;
+class CTxMemPool;
+
+namespace kernel {
+
+/** Dump the mempool to disk. */
+bool DumpMempool(const CTxMemPool& pool, const fs::path& dump_path,
+ fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen,
+ bool skip_file_commit = false);
+
+/** Load the mempool from disk. */
+bool LoadMempool(CTxMemPool& pool, const fs::path& load_path,
+ Chainstate& active_chainstate,
+ fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen);
+
+} // namespace kernel
+
+
+#endif // BITCOIN_KERNEL_MEMPOOL_PERSIST_H
diff --git a/src/kernel/validation_cache_sizes.h b/src/kernel/validation_cache_sizes.h
new file mode 100644
index 0000000000..72e4d1a52c
--- /dev/null
+++ b/src/kernel/validation_cache_sizes.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H
+#define BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H
+
+#include <script/sigcache.h>
+
+#include <cstddef>
+#include <limits>
+
+namespace kernel {
+struct ValidationCacheSizes {
+ size_t signature_cache_bytes{DEFAULT_MAX_SIG_CACHE_BYTES / 2};
+ size_t script_execution_cache_bytes{DEFAULT_MAX_SIG_CACHE_BYTES / 2};
+};
+}
+
+#endif // BITCOIN_KERNEL_VALIDATION_CACHE_SIZES_H
diff --git a/src/key.cpp b/src/key.cpp
index 9b0971a2dd..199808505d 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -333,6 +333,7 @@ bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const
}
bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {
+ if (nDepth == std::numeric_limits<unsigned char>::max()) return false;
out.nDepth = nDepth + 1;
CKeyID id = key.GetPubKey().GetID();
memcpy(out.vchFingerprint, &id, 4);
diff --git a/src/key.h b/src/key.h
index 12d03778a0..e9b78ebd44 100644
--- a/src/key.h
+++ b/src/key.h
@@ -146,7 +146,7 @@ public:
bool SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256* merkle_root, const uint256& aux) const;
//! Derive BIP32 child key.
- bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
+ [[nodiscard]] bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
/**
* Verify thoroughly whether a private key and a public key match.
@@ -176,7 +176,7 @@ struct CExtKey {
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
- bool Derive(CExtKey& out, unsigned int nChild) const;
+ [[nodiscard]] bool Derive(CExtKey& out, unsigned int nChild) const;
CExtPubKey Neuter() const;
void SetSeed(Span<const std::byte> seed);
};
diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc
index 18626b327c..fac41be6ce 100644
--- a/src/leveldb/util/env_posix.cc
+++ b/src/leveldb/util/env_posix.cc
@@ -49,7 +49,7 @@ constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 4096 : 0;
int g_mmap_limit = kDefaultMmapLimit;
// Common flags defined for all posix open operations
-#if defined(HAVE_O_CLOEXEC)
+#if HAVE_O_CLOEXEC
constexpr const int kOpenBaseFlags = O_CLOEXEC;
#else
constexpr const int kOpenBaseFlags = 0;
diff --git a/src/logging.cpp b/src/logging.cpp
index 1e2c1d5a77..a3f1d39be5 100644
--- a/src/logging.cpp
+++ b/src/logging.cpp
@@ -5,15 +5,17 @@
#include <fs.h>
#include <logging.h>
-#include <util/threadnames.h>
#include <util/string.h>
+#include <util/threadnames.h>
#include <util/time.h>
#include <algorithm>
#include <array>
#include <mutex>
+#include <optional>
const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
+constexpr auto MAX_USER_SETABLE_SEVERITY_LEVEL{BCLog::Level::Info};
BCLog::Logger& LogInstance()
{
@@ -122,6 +124,19 @@ bool BCLog::Logger::WillLogCategory(BCLog::LogFlags category) const
return (m_categories.load(std::memory_order_relaxed) & category) != 0;
}
+bool BCLog::Logger::WillLogCategoryLevel(BCLog::LogFlags category, BCLog::Level level) const
+{
+ // Log messages at Warning and Error level unconditionally, so that
+ // important troubleshooting information doesn't get lost.
+ if (level >= BCLog::Level::Warning) return true;
+
+ if (!WillLogCategory(category)) return false;
+
+ StdLockGuard scoped_lock(m_cs);
+ const auto it{m_category_log_levels.find(category)};
+ return level >= (it == m_category_log_levels.end() ? LogLevel() : it->second);
+}
+
bool BCLog::Logger::DefaultShrinkDebugFile() const
{
return m_categories == BCLog::NONE;
@@ -135,7 +150,7 @@ struct CLogCategoryDesc {
const CLogCategoryDesc LogCategories[] =
{
{BCLog::NONE, "0"},
- {BCLog::NONE, "none"},
+ {BCLog::NONE, ""},
{BCLog::NET, "net"},
{BCLog::TOR, "tor"},
{BCLog::MEMPOOL, "mempool"},
@@ -184,11 +199,11 @@ bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str)
return false;
}
-std::string LogLevelToStr(BCLog::Level level)
+std::string BCLog::Logger::LogLevelToStr(BCLog::Level level) const
{
switch (level) {
- case BCLog::Level::None:
- return "none";
+ case BCLog::Level::Trace:
+ return "trace";
case BCLog::Level::Debug:
return "debug";
case BCLog::Level::Info:
@@ -197,6 +212,8 @@ std::string LogLevelToStr(BCLog::Level level)
return "warning";
case BCLog::Level::Error:
return "error";
+ case BCLog::Level::None:
+ return "";
}
assert(false);
}
@@ -206,7 +223,7 @@ std::string LogCategoryToStr(BCLog::LogFlags category)
// Each log category string representation should sync with LogCategories
switch (category) {
case BCLog::LogFlags::NONE:
- return "none";
+ return "";
case BCLog::LogFlags::NET:
return "net";
case BCLog::LogFlags::TOR:
@@ -269,6 +286,25 @@ std::string LogCategoryToStr(BCLog::LogFlags category)
assert(false);
}
+static std::optional<BCLog::Level> GetLogLevel(const std::string& level_str)
+{
+ if (level_str == "trace") {
+ return BCLog::Level::Trace;
+ } else if (level_str == "debug") {
+ return BCLog::Level::Debug;
+ } else if (level_str == "info") {
+ return BCLog::Level::Info;
+ } else if (level_str == "warning") {
+ return BCLog::Level::Warning;
+ } else if (level_str == "error") {
+ return BCLog::Level::Error;
+ } else if (level_str == "none") {
+ return BCLog::Level::None;
+ } else {
+ return std::nullopt;
+ }
+}
+
std::vector<LogCategory> BCLog::Logger::LogCategoriesList() const
{
// Sort log categories by alphabetical order.
@@ -287,6 +323,18 @@ std::vector<LogCategory> BCLog::Logger::LogCategoriesList() const
return ret;
}
+/** Log severity levels that can be selected by the user. */
+static constexpr std::array<BCLog::Level, 3> LogLevelsList()
+{
+ return {BCLog::Level::Info, BCLog::Level::Debug, BCLog::Level::Trace};
+}
+
+std::string BCLog::Logger::LogLevelsString() const
+{
+ const auto& levels = LogLevelsList();
+ return Join(std::vector<BCLog::Level>{levels.begin(), levels.end()}, ", ", [this](BCLog::Level level) { return LogLevelToStr(level); });
+}
+
std::string BCLog::Logger::LogTimestampStr(const std::string& str)
{
std::string strStamped;
@@ -334,7 +382,7 @@ namespace BCLog {
}
} // namespace BCLog
-void BCLog::Logger::LogPrintStr(const std::string& str, const std::string& logging_function, const std::string& source_file, const int source_line, const BCLog::LogFlags category, const BCLog::Level level)
+void BCLog::Logger::LogPrintStr(const std::string& str, const std::string& logging_function, const std::string& source_file, int source_line, BCLog::LogFlags category, BCLog::Level level)
{
StdLockGuard scoped_lock(m_cs);
std::string str_prefixed = LogEscapeMessage(str);
@@ -364,7 +412,7 @@ void BCLog::Logger::LogPrintStr(const std::string& str, const std::string& loggi
}
if (m_log_threadnames && m_started_new_line) {
- const auto threadname = util::ThreadGetInternalName();
+ const auto& threadname = util::ThreadGetInternalName();
str_prefixed.insert(0, "[" + (threadname.empty() ? "unknown" : threadname) + "] ");
}
@@ -443,3 +491,24 @@ void BCLog::Logger::ShrinkDebugFile()
else if (file != nullptr)
fclose(file);
}
+
+bool BCLog::Logger::SetLogLevel(const std::string& level_str)
+{
+ const auto level = GetLogLevel(level_str);
+ if (!level.has_value() || level.value() > MAX_USER_SETABLE_SEVERITY_LEVEL) return false;
+ m_log_level = level.value();
+ return true;
+}
+
+bool BCLog::Logger::SetCategoryLogLevel(const std::string& category_str, const std::string& level_str)
+{
+ BCLog::LogFlags flag;
+ if (!GetLogCategory(flag, category_str)) return false;
+
+ const auto level = GetLogLevel(level_str);
+ if (!level.has_value() || level.value() > MAX_USER_SETABLE_SEVERITY_LEVEL) return false;
+
+ StdLockGuard scoped_lock(m_cs);
+ m_category_log_levels[flag] = level.value();
+ return true;
+}
diff --git a/src/logging.h b/src/logging.h
index 50869ad89a..fe91ee43a5 100644
--- a/src/logging.h
+++ b/src/logging.h
@@ -7,8 +7,8 @@
#define BITCOIN_LOGGING_H
#include <fs.h>
-#include <tinyformat.h>
#include <threadsafety.h>
+#include <tinyformat.h>
#include <util/string.h>
#include <atomic>
@@ -17,6 +17,7 @@
#include <list>
#include <mutex>
#include <string>
+#include <unordered_map>
#include <vector>
static const bool DEFAULT_LOGTIMEMICROS = false;
@@ -68,12 +69,14 @@ namespace BCLog {
ALL = ~(uint32_t)0,
};
enum class Level {
- Debug = 0,
- None = 1,
- Info = 2,
- Warning = 3,
- Error = 4,
+ Trace = 0, // High-volume or detailed logging for development/debugging
+ Debug, // Reasonably noisy logging, but still usable in production
+ Info, // Default
+ Warning,
+ Error,
+ None, // Internal use only
};
+ constexpr auto DEFAULT_LOG_LEVEL{Level::Debug};
class Logger
{
@@ -91,6 +94,13 @@ namespace BCLog {
*/
std::atomic_bool m_started_new_line{true};
+ //! Category-specific log level. Overrides `m_log_level`.
+ std::unordered_map<LogFlags, Level> m_category_log_levels GUARDED_BY(m_cs);
+
+ //! If there is no category-specific log level, all logs with a severity
+ //! level lower than `m_log_level` will be ignored.
+ std::atomic<Level> m_log_level{DEFAULT_LOG_LEVEL};
+
/** Log categories bitfield. */
std::atomic<uint32_t> m_categories{0};
@@ -112,7 +122,7 @@ namespace BCLog {
std::atomic<bool> m_reopen_file{false};
/** Send a string to the log output */
- void LogPrintStr(const std::string& str, const std::string& logging_function, const std::string& source_file, const int source_line, const BCLog::LogFlags category, const BCLog::Level level);
+ void LogPrintStr(const std::string& str, const std::string& logging_function, const std::string& source_file, int source_line, BCLog::LogFlags category, BCLog::Level level);
/** Returns whether logs will be written to any output */
bool Enabled() const
@@ -143,6 +153,22 @@ namespace BCLog {
void ShrinkDebugFile();
+ std::unordered_map<LogFlags, Level> CategoryLevels() const
+ {
+ StdLockGuard scoped_lock(m_cs);
+ return m_category_log_levels;
+ }
+ void SetCategoryLogLevel(const std::unordered_map<LogFlags, Level>& levels)
+ {
+ StdLockGuard scoped_lock(m_cs);
+ m_category_log_levels = levels;
+ }
+ bool SetCategoryLogLevel(const std::string& category_str, const std::string& level_str);
+
+ Level LogLevel() const { return m_log_level.load(); }
+ void SetLogLevel(Level level) { m_log_level = level; }
+ bool SetLogLevel(const std::string& level);
+
uint32_t GetCategoryMask() const { return m_categories.load(); }
void EnableCategory(LogFlags flag);
@@ -151,6 +177,8 @@ namespace BCLog {
bool DisableCategory(const std::string& str);
bool WillLogCategory(LogFlags category) const;
+ bool WillLogCategoryLevel(LogFlags category, Level level) const;
+
/** Returns a vector of the log categories in alphabetical order. */
std::vector<LogCategory> LogCategoriesList() const;
/** Returns a string with the log categories in alphabetical order. */
@@ -159,6 +187,12 @@ namespace BCLog {
return Join(LogCategoriesList(), ", ", [&](const LogCategory& i) { return i.category; });
};
+ //! Returns a string with all user-selectable log levels.
+ std::string LogLevelsString() const;
+
+ //! Returns the string representation of a log level.
+ std::string LogLevelToStr(BCLog::Level level) const;
+
bool DefaultShrinkDebugFile() const;
};
@@ -169,12 +203,7 @@ BCLog::Logger& LogInstance();
/** Return true if log accepts specified category, at the specified level. */
static inline bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
{
- // Log messages at Warning and Error level unconditionally, so that
- // important troubleshooting information doesn't get lost.
- if (level >= BCLog::Level::Warning) {
- return true;
- }
- return LogInstance().WillLogCategory(category);
+ return LogInstance().WillLogCategoryLevel(category, level);
}
/** Return true if str parses as a log category and set the flag */
diff --git a/src/mapport.cpp b/src/mapport.cpp
index 235e6f904c..6262e51879 100644
--- a/src/mapport.cpp
+++ b/src/mapport.cpp
@@ -19,7 +19,7 @@
#include <util/thread.h>
#ifdef USE_NATPMP
-#include <compat.h>
+#include <compat/compat.h>
#include <natpmp.h>
#endif // USE_NATPMP
diff --git a/src/minisketch/README.md b/src/minisketch/README.md
index c0cfdc1623..f8b89ff33e 100644
--- a/src/minisketch/README.md
+++ b/src/minisketch/README.md
@@ -203,8 +203,8 @@ Some improvements that are still TODO:
* <a name="myfootnote4">[4]</a> Bhaskar Biswas, Vincent Herbert. *Efficient Root Finding of Polynomials over Fields of Characteristic 2.* 2009. hal-00626997. [[URL]](https://hal.archives-ouvertes.fr/hal-00626997) [[PDF]](https://hal.archives-ouvertes.fr/hal-00626997/document)
* <a name="myfootnote6">[6]</a> Eppstein, David, Michael T. Goodrich, Frank Uyeda, and George Varghese. *What's the difference?: efficient set reconciliation without prior context.* ACM SIGCOMM Computer Communication Review, vol. 41, no. 4, pp. 218-229. ACM, 2011. [[PDF]](https://www.ics.uci.edu/~eppstein/pubs/EppGooUye-SIGCOMM-11.pdf)
* <a name="myfootnote7">[7]</a> Goodrich, Michael T. and Michael Mitzenmacher. *Invertible bloom lookup tables.* 2011 49th Annual Allerton Conference on Communication, Control, and Computing (Allerton) (2011): 792-799. [[PDF]](https://arxiv.org/pdf/1101.2245.pdf)
-* <a name="myfootnote8">[8]</a> Maxwell, Gregory F. *[Blocksonly mode BW savings, the limits of efficient block xfer, and better relay](https://bitcointalk.org/index.php?topic=1377345.0)* Bitcointalk 2016, *[Technical notes on mempool synchronizing relay](https://people.xiph.org/~greg/mempool_sync_relay.txt)* #bitcoin-wizards 2016.
-* <a name="myfootnote9">[9]</a> Maxwell, Gregory F. *[Block network coding](https://en.bitcoin.it/wiki/User:Gmaxwell/block_network_coding)* Bitcoin Wiki 2014, *[Technical notes on efficient block xfer](https://people.xiph.org/~greg/efficient.block.xfer.txt)* #bitcoin-wizards 2015.
+* <a name="myfootnote8">[8]</a> Maxwell, Gregory F. *[Blocksonly mode BW savings, the limits of efficient block xfer, and better relay](https://bitcointalk.org/index.php?topic=1377345.0)* Bitcointalk 2016, *[Technical notes on mempool synchronizing relay](https://nt4tn.net/tech-notes/2016.mempool_sync_relay.txt)* #bitcoin-wizards 2016.
+* <a name="myfootnote9">[9]</a> Maxwell, Gregory F. *[Block network coding](https://en.bitcoin.it/wiki/User:Gmaxwell/block_network_coding)* Bitcoin Wiki 2014, *[Technical notes on efficient block xfer](https://nt4tn.net/tech-notes/201512.efficient.block.xfer.txt)* #bitcoin-wizards 2015.
* <a name="myfootnote10">[10]</a> Ruffing, Tim, Moreno-Sanchez, Pedro, Aniket, Kate, *P2P Mixing and Unlinkable Bitcoin Transactions* NDSS Symposium 2017 [[URL]](https://eprint.iacr.org/2016/824) [[PDF]](https://eprint.iacr.org/2016/824.pdf)
* <a name="myfootnote11">[11]</a> Y. Misky, A. Trachtenberg, R. Zippel. *Set Reconciliation with Nearly Optimal Communication Complexity.* Cornell University, 2000. [[URL]](https://ecommons.cornell.edu/handle/1813/5803) [[PDF]](https://ecommons.cornell.edu/bitstream/handle/1813/5803/2000-1813.pdf)
* <a name="myfootnote12">[12]</a> Itoh, Toshiya, and Shigeo Tsujii. "A fast algorithm for computing multiplicative inverses in GF (2m) using normal bases." Information and computation 78, no. 3 (1988): 171-177. [[URL]](https://www.sciencedirect.com/science/article/pii/0890540188900247)
diff --git a/src/minisketch/include/minisketch.h b/src/minisketch/include/minisketch.h
index 0b5d8372e8..24d6b4e1c0 100644
--- a/src/minisketch/include/minisketch.h
+++ b/src/minisketch/include/minisketch.h
@@ -5,7 +5,8 @@
#include <stdlib.h>
#ifdef _MSC_VER
-# include <compat.h>
+# include <BaseTsd.h>
+ typedef SSIZE_T ssize_t;
#else
# include <unistd.h>
#endif
diff --git a/src/net.cpp b/src/net.cpp
index c05fa771ef..0cc14b1d2a 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -13,9 +13,10 @@
#include <addrman.h>
#include <banman.h>
#include <clientversion.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <consensus/consensus.h>
#include <crypto/sha256.h>
+#include <node/eviction.h>
#include <fs.h>
#include <i2p.h>
#include <net_permissions.h>
@@ -25,7 +26,6 @@
#include <protocol.h>
#include <random.h>
#include <scheduler.h>
-#include <util/designator.h>
#include <util/sock.h>
#include <util/strencodings.h>
#include <util/syscall_sandbox.h>
@@ -85,8 +85,8 @@ static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD = 1000; // "many" vs "few" pe
/** The default timeframe for -maxuploadtarget. 1 day. */
static constexpr std::chrono::seconds MAX_UPLOAD_TIMEFRAME{60 * 60 * 24};
-// We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
-#define FEELER_SLEEP_WINDOW 1
+// A random time period (0 to 1 seconds) is added to feeler connections to prevent synchronization.
+static constexpr auto FEELER_SLEEP_WINDOW{1s};
/** Used to pass flags to the Bind() function */
enum BindFlags {
@@ -187,7 +187,7 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
// it'll get a pile of addresses with newer timestamps.
// Seed nodes are given a random 'last seen time' of between one and two
// weeks ago.
- const int64_t nOneWeek = 7*24*60*60;
+ const auto one_week{7 * 24h};
std::vector<CAddress> vSeedsOut;
FastRandomContext rng;
CDataStream s(vSeedsIn, SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
@@ -195,7 +195,7 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
CService endpoint;
s >> endpoint;
CAddress addr{endpoint, GetDesirableServiceFlags(NODE_NONE)};
- addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek;
+ addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - one_week, -one_week);
LogPrint(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToString());
vSeedsOut.push_back(addr);
}
@@ -206,16 +206,13 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
// Otherwise, return the unroutable 0.0.0.0 but filled in with
// the normal parameters, since the IP may be changed to a useful
// one by discovery.
-CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
+CService GetLocalAddress(const CNetAddr& addrPeer)
{
- CAddress ret(CService(CNetAddr(),GetListenPort()), nLocalServices);
CService addr;
- if (GetLocal(addr, paddrPeer))
- {
- ret = CAddress(addr, nLocalServices);
+ if (GetLocal(addr, &addrPeer)) {
+ return addr;
}
- ret.nTime = GetAdjustedTime();
- return ret;
+ return CService{CNetAddr(), GetListenPort()};
}
static int GetnScore(const CService& addr)
@@ -233,35 +230,35 @@ bool IsPeerAddrLocalGood(CNode *pnode)
IsReachable(addrLocal.GetNetwork());
}
-std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
+std::optional<CService> GetLocalAddrForPeer(CNode& node)
{
- CAddress addrLocal = GetLocalAddress(&pnode->addr, pnode->GetLocalServices());
+ CService addrLocal{GetLocalAddress(node.addr)};
if (gArgs.GetBoolArg("-addrmantest", false)) {
// use IPv4 loopback during addrmantest
- addrLocal = CAddress(CService(LookupNumeric("127.0.0.1", GetListenPort())), pnode->GetLocalServices());
+ addrLocal = CService(LookupNumeric("127.0.0.1", GetListenPort()));
}
// If discovery is enabled, sometimes give our peer the address it
// tells us that it sees us as in case it has a better idea of our
// address than we do.
FastRandomContext rng;
- if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
+ if (IsPeerAddrLocalGood(&node) && (!addrLocal.IsRoutable() ||
rng.randbits((GetnScore(addrLocal) > LOCAL_MANUAL) ? 3 : 1) == 0))
{
- if (pnode->IsInboundConn()) {
+ if (node.IsInboundConn()) {
// For inbound connections, assume both the address and the port
// as seen from the peer.
- addrLocal = CAddress{pnode->GetAddrLocal(), addrLocal.nServices, addrLocal.nTime};
+ addrLocal = CService{node.GetAddrLocal()};
} else {
// For outbound connections, assume just the address as seen from
// the peer and leave the port in `addrLocal` as returned by
// `GetLocalAddress()` above. The peer has no way to observe our
// listening port when we have initiated the connection.
- addrLocal.SetIP(pnode->GetAddrLocal());
+ addrLocal.SetIP(node.GetAddrLocal());
}
}
if (addrLocal.IsRoutable() || gArgs.GetBoolArg("-addrmantest", false))
{
- LogPrint(BCLog::NET, "Advertising address %s to peer=%d\n", addrLocal.ToString(), pnode->GetId());
+ LogPrint(BCLog::NET, "Advertising address %s to peer=%d\n", addrLocal.ToString(), node.GetId());
return addrLocal;
}
// Address is unroutable. Don't advertise.
@@ -422,13 +419,13 @@ bool CConnman::CheckIncomingNonce(uint64_t nonce)
}
/** Get the bind address for a socket as CAddress */
-static CAddress GetBindAddress(SOCKET sock)
+static CAddress GetBindAddress(const Sock& sock)
{
CAddress addr_bind;
struct sockaddr_storage sockaddr_bind;
socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
- if (sock != INVALID_SOCKET) {
- if (!getsockname(sock, (struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
+ if (sock.Get() != INVALID_SOCKET) {
+ if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
} else {
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
@@ -454,10 +451,9 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
}
}
- /// debug print
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "trying connection %s lastseen=%.1fhrs\n",
- pszDest ? pszDest : addrConnect.ToString(),
- pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime) / 3600.0);
+ pszDest ? pszDest : addrConnect.ToString(),
+ Ticks<HoursDouble>(pszDest ? 0h : Now<NodeSeconds>() - addrConnect.nTime));
// Resolve
const uint16_t default_port{pszDest != nullptr ? Params().GetDefaultPort(pszDest) :
@@ -488,18 +484,27 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
Proxy proxy;
CAddress addr_bind;
assert(!addr_bind.IsValid());
+ std::unique_ptr<i2p::sam::Session> i2p_transient_session;
if (addrConnect.IsValid()) {
+ const bool use_proxy{GetProxy(addrConnect.GetNetwork(), proxy)};
bool proxyConnectionFailed = false;
- if (addrConnect.GetNetwork() == NET_I2P && m_i2p_sam_session.get() != nullptr) {
+ if (addrConnect.GetNetwork() == NET_I2P && use_proxy) {
i2p::Connection conn;
- if (m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed)) {
- connected = true;
+
+ if (m_i2p_sam_session) {
+ connected = m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed);
+ } else {
+ i2p_transient_session = std::make_unique<i2p::sam::Session>(proxy.proxy, &interruptNet);
+ connected = i2p_transient_session->Connect(addrConnect, conn, proxyConnectionFailed);
+ }
+
+ if (connected) {
sock = std::move(conn.sock);
addr_bind = CAddress{conn.me, NODE_NONE};
}
- } else if (GetProxy(addrConnect.GetNetwork(), proxy)) {
+ } else if (use_proxy) {
sock = CreateSock(proxy.proxy);
if (!sock) {
return nullptr;
@@ -540,10 +545,9 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
if (!addr_bind.IsValid()) {
- addr_bind = GetBindAddress(sock->Get());
+ addr_bind = GetBindAddress(*sock);
}
CNode* pnode = new CNode(id,
- nLocalServices,
std::move(sock),
addrConnect,
CalculateKeyedNetGroup(addrConnect),
@@ -551,7 +555,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
addr_bind,
pszDest ? pszDest : "",
conn_type,
- /*inbound_onion=*/false);
+ /*inbound_onion=*/false,
+ CNodeOptions{ .i2p_sam_session = std::move(i2p_transient_session) });
pnode->AddRef();
// We're making a new connection, harvest entropy from the time (and our peer count)
@@ -568,6 +573,7 @@ void CNode::CloseSocketDisconnect()
LogPrint(BCLog::NET, "disconnecting peer=%d\n", id);
m_sock.reset();
}
+ m_i2p_sam_session.reset();
}
void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const {
@@ -576,26 +582,6 @@ void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNet
}
}
-std::string ConnectionTypeAsString(ConnectionType conn_type)
-{
- switch (conn_type) {
- case ConnectionType::INBOUND:
- return "inbound";
- case ConnectionType::MANUAL:
- return "manual";
- case ConnectionType::FEELER:
- return "feeler";
- case ConnectionType::OUTBOUND_FULL_RELAY:
- return "outbound-full-relay";
- case ConnectionType::BLOCK_RELAY:
- return "block-relay-only";
- case ConnectionType::ADDR_FETCH:
- return "addr-fetch";
- } // no default case, so the compiler can warn about missing cases
-
- assert(false);
-}
-
CService CNode::GetAddrLocal() const
{
AssertLockNotHeld(m_addr_local_mutex);
@@ -623,7 +609,6 @@ Network CNode::ConnectedThroughNetwork() const
void CNode::CopyStats(CNodeStats& stats)
{
stats.nodeid = this->GetId();
- X(nServices);
X(addr);
X(addrBind);
stats.m_network = ConnectedThroughNetwork();
@@ -652,7 +637,7 @@ void CNode::CopyStats(CNodeStats& stats)
X(mapRecvBytesPerMsgType);
X(nRecvBytes);
}
- X(m_permissionFlags);
+ X(m_permission_flags);
X(m_last_ping_time);
X(m_min_ping_time);
@@ -812,7 +797,8 @@ CNetMessage V1TransportDeserializer::GetMessage(const std::chrono::microseconds
return msg;
}
-void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) {
+void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) const
+{
// create dbl-sha256 checksum
uint256 hash = Hash(msg.data);
@@ -877,210 +863,6 @@ size_t CConnman::SocketSendData(CNode& node) const
return nSentSize;
}
-static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
-{
- return a.m_min_ping_time > b.m_min_ping_time;
-}
-
-static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
-{
- return a.m_connected > b.m_connected;
-}
-
-static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) {
- return a.nKeyedNetGroup < b.nKeyedNetGroup;
-}
-
-static bool CompareNodeBlockTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
-{
- // There is a fall-through here because it is common for a node to have many peers which have not yet relayed a block.
- if (a.m_last_block_time != b.m_last_block_time) return a.m_last_block_time < b.m_last_block_time;
- if (a.fRelevantServices != b.fRelevantServices) return b.fRelevantServices;
- return a.m_connected > b.m_connected;
-}
-
-static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
-{
- // There is a fall-through here because it is common for a node to have more than a few peers that have not yet relayed txn.
- if (a.m_last_tx_time != b.m_last_tx_time) return a.m_last_tx_time < b.m_last_tx_time;
- if (a.m_relay_txs != b.m_relay_txs) return b.m_relay_txs;
- if (a.fBloomFilter != b.fBloomFilter) return a.fBloomFilter;
- return a.m_connected > b.m_connected;
-}
-
-// Pick out the potential block-relay only peers, and sort them by last block time.
-static bool CompareNodeBlockRelayOnlyTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
-{
- if (a.m_relay_txs != b.m_relay_txs) return a.m_relay_txs;
- if (a.m_last_block_time != b.m_last_block_time) return a.m_last_block_time < b.m_last_block_time;
- if (a.fRelevantServices != b.fRelevantServices) return b.fRelevantServices;
- return a.m_connected > b.m_connected;
-}
-
-/**
- * Sort eviction candidates by network/localhost and connection uptime.
- * Candidates near the beginning are more likely to be evicted, and those
- * near the end are more likely to be protected, e.g. less likely to be evicted.
- * - First, nodes that are not `is_local` and that do not belong to `network`,
- * sorted by increasing uptime (from most recently connected to connected longer).
- * - Then, nodes that are `is_local` or belong to `network`, sorted by increasing uptime.
- */
-struct CompareNodeNetworkTime {
- const bool m_is_local;
- const Network m_network;
- CompareNodeNetworkTime(bool is_local, Network network) : m_is_local(is_local), m_network(network) {}
- bool operator()(const NodeEvictionCandidate& a, const NodeEvictionCandidate& b) const
- {
- if (m_is_local && a.m_is_local != b.m_is_local) return b.m_is_local;
- if ((a.m_network == m_network) != (b.m_network == m_network)) return b.m_network == m_network;
- return a.m_connected > b.m_connected;
- };
-};
-
-//! Sort an array by the specified comparator, then erase the last K elements where predicate is true.
-template <typename T, typename Comparator>
-static void EraseLastKElements(
- std::vector<T>& elements, Comparator comparator, size_t k,
- std::function<bool(const NodeEvictionCandidate&)> predicate = [](const NodeEvictionCandidate& n) { return true; })
-{
- std::sort(elements.begin(), elements.end(), comparator);
- size_t eraseSize = std::min(k, elements.size());
- elements.erase(std::remove_if(elements.end() - eraseSize, elements.end(), predicate), elements.end());
-}
-
-void ProtectEvictionCandidatesByRatio(std::vector<NodeEvictionCandidate>& eviction_candidates)
-{
- // Protect the half of the remaining nodes which have been connected the longest.
- // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
- // To favorise the diversity of our peer connections, reserve up to half of these protected
- // spots for Tor/onion, localhost, I2P, and CJDNS peers, even if they're not longest uptime
- // overall. This helps protect these higher-latency peers that tend to be otherwise
- // disadvantaged under our eviction criteria.
- const size_t initial_size = eviction_candidates.size();
- const size_t total_protect_size{initial_size / 2};
-
- // Disadvantaged networks to protect. In the case of equal counts, earlier array members
- // have the first opportunity to recover unused slots from the previous iteration.
- struct Net { bool is_local; Network id; size_t count; };
- std::array<Net, 4> networks{
- {{false, NET_CJDNS, 0}, {false, NET_I2P, 0}, {/*localhost=*/true, NET_MAX, 0}, {false, NET_ONION, 0}}};
-
- // Count and store the number of eviction candidates per network.
- for (Net& n : networks) {
- n.count = std::count_if(eviction_candidates.cbegin(), eviction_candidates.cend(),
- [&n](const NodeEvictionCandidate& c) {
- return n.is_local ? c.m_is_local : c.m_network == n.id;
- });
- }
- // Sort `networks` by ascending candidate count, to give networks having fewer candidates
- // the first opportunity to recover unused protected slots from the previous iteration.
- std::stable_sort(networks.begin(), networks.end(), [](Net a, Net b) { return a.count < b.count; });
-
- // Protect up to 25% of the eviction candidates by disadvantaged network.
- const size_t max_protect_by_network{total_protect_size / 2};
- size_t num_protected{0};
-
- while (num_protected < max_protect_by_network) {
- // Count the number of disadvantaged networks from which we have peers to protect.
- auto num_networks = std::count_if(networks.begin(), networks.end(), [](const Net& n) { return n.count; });
- if (num_networks == 0) {
- break;
- }
- const size_t disadvantaged_to_protect{max_protect_by_network - num_protected};
- const size_t protect_per_network{std::max(disadvantaged_to_protect / num_networks, static_cast<size_t>(1))};
- // Early exit flag if there are no remaining candidates by disadvantaged network.
- bool protected_at_least_one{false};
-
- for (Net& n : networks) {
- if (n.count == 0) continue;
- const size_t before = eviction_candidates.size();
- EraseLastKElements(eviction_candidates, CompareNodeNetworkTime(n.is_local, n.id),
- protect_per_network, [&n](const NodeEvictionCandidate& c) {
- return n.is_local ? c.m_is_local : c.m_network == n.id;
- });
- const size_t after = eviction_candidates.size();
- if (before > after) {
- protected_at_least_one = true;
- const size_t delta{before - after};
- num_protected += delta;
- if (num_protected >= max_protect_by_network) {
- break;
- }
- n.count -= delta;
- }
- }
- if (!protected_at_least_one) {
- break;
- }
- }
-
- // Calculate how many we removed, and update our total number of peers that
- // we want to protect based on uptime accordingly.
- assert(num_protected == initial_size - eviction_candidates.size());
- const size_t remaining_to_protect{total_protect_size - num_protected};
- EraseLastKElements(eviction_candidates, ReverseCompareNodeTimeConnected, remaining_to_protect);
-}
-
-[[nodiscard]] std::optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
-{
- // Protect connections with certain characteristics
-
- // Deterministically select 4 peers to protect by netgroup.
- // An attacker cannot predict which netgroups will be protected
- EraseLastKElements(vEvictionCandidates, CompareNetGroupKeyed, 4);
- // Protect the 8 nodes with the lowest minimum ping time.
- // An attacker cannot manipulate this metric without physically moving nodes closer to the target.
- EraseLastKElements(vEvictionCandidates, ReverseCompareNodeMinPingTime, 8);
- // Protect 4 nodes that most recently sent us novel transactions accepted into our mempool.
- // An attacker cannot manipulate this metric without performing useful work.
- EraseLastKElements(vEvictionCandidates, CompareNodeTXTime, 4);
- // Protect up to 8 non-tx-relay peers that have sent us novel blocks.
- EraseLastKElements(vEvictionCandidates, CompareNodeBlockRelayOnlyTime, 8,
- [](const NodeEvictionCandidate& n) { return !n.m_relay_txs && n.fRelevantServices; });
-
- // Protect 4 nodes that most recently sent us novel blocks.
- // An attacker cannot manipulate this metric without performing useful work.
- EraseLastKElements(vEvictionCandidates, CompareNodeBlockTime, 4);
-
- // Protect some of the remaining eviction candidates by ratios of desirable
- // or disadvantaged characteristics.
- ProtectEvictionCandidatesByRatio(vEvictionCandidates);
-
- if (vEvictionCandidates.empty()) return std::nullopt;
-
- // If any remaining peers are preferred for eviction consider only them.
- // This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
- // then we probably don't want to evict it no matter what.
- if (std::any_of(vEvictionCandidates.begin(),vEvictionCandidates.end(),[](NodeEvictionCandidate const &n){return n.prefer_evict;})) {
- vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.begin(),vEvictionCandidates.end(),
- [](NodeEvictionCandidate const &n){return !n.prefer_evict;}),vEvictionCandidates.end());
- }
-
- // Identify the network group with the most connections and youngest member.
- // (vEvictionCandidates is already sorted by reverse connect time)
- uint64_t naMostConnections;
- unsigned int nMostConnections = 0;
- std::chrono::seconds nMostConnectionsTime{0};
- std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapNetGroupNodes;
- for (const NodeEvictionCandidate &node : vEvictionCandidates) {
- std::vector<NodeEvictionCandidate> &group = mapNetGroupNodes[node.nKeyedNetGroup];
- group.push_back(node);
- const auto grouptime{group[0].m_connected};
-
- if (group.size() > nMostConnections || (group.size() == nMostConnections && grouptime > nMostConnectionsTime)) {
- nMostConnections = group.size();
- nMostConnectionsTime = grouptime;
- naMostConnections = node.nKeyedNetGroup;
- }
- }
-
- // Reduce to the network group with the most connections
- vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
-
- // Disconnect from the network group with the most connections
- return vEvictionCandidates.front().id;
-}
-
/** Try to find a connection to evict when the node is full.
* Extreme care must be taken to avoid opening the node to attacker
* triggered network partitioning.
@@ -1096,25 +878,23 @@ bool CConnman::AttemptToEvictConnection()
LOCK(m_nodes_mutex);
for (const CNode* node : m_nodes) {
- if (node->HasPermission(NetPermissionFlags::NoBan))
- continue;
- if (!node->IsInboundConn())
- continue;
if (node->fDisconnect)
continue;
NodeEvictionCandidate candidate{
- Desig(id) node->GetId(),
- Desig(m_connected) node->m_connected,
- Desig(m_min_ping_time) node->m_min_ping_time,
- Desig(m_last_block_time) node->m_last_block_time,
- Desig(m_last_tx_time) node->m_last_tx_time,
- Desig(fRelevantServices) HasAllDesirableServiceFlags(node->nServices),
- Desig(m_relay_txs) node->m_relays_txs.load(),
- Desig(fBloomFilter) node->m_bloom_filter_loaded.load(),
- Desig(nKeyedNetGroup) node->nKeyedNetGroup,
- Desig(prefer_evict) node->m_prefer_evict,
- Desig(m_is_local) node->addr.IsLocal(),
- Desig(m_network) node->ConnectedThroughNetwork(),
+ .id = node->GetId(),
+ .m_connected = node->m_connected,
+ .m_min_ping_time = node->m_min_ping_time,
+ .m_last_block_time = node->m_last_block_time,
+ .m_last_tx_time = node->m_last_tx_time,
+ .fRelevantServices = node->m_has_all_wanted_services,
+ .m_relay_txs = node->m_relays_txs.load(),
+ .fBloomFilter = node->m_bloom_filter_loaded.load(),
+ .nKeyedNetGroup = node->nKeyedNetGroup,
+ .prefer_evict = node->m_prefer_evict,
+ .m_is_local = node->addr.IsLocal(),
+ .m_network = node->ConnectedThroughNetwork(),
+ .m_noban = node->HasPermission(NetPermissionFlags::NoBan),
+ .m_conn_type = node->m_conn_type,
};
vEvictionCandidates.push_back(candidate);
}
@@ -1154,29 +934,29 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};
}
- const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(sock->Get())), NODE_NONE};
+ const CAddress addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock)), NODE_NONE};
- NetPermissionFlags permissionFlags = NetPermissionFlags::None;
- hListenSocket.AddSocketPermissionFlags(permissionFlags);
+ NetPermissionFlags permission_flags = NetPermissionFlags::None;
+ hListenSocket.AddSocketPermissionFlags(permission_flags);
- CreateNodeFromAcceptedSocket(std::move(sock), permissionFlags, addr_bind, addr);
+ CreateNodeFromAcceptedSocket(std::move(sock), permission_flags, addr_bind, addr);
}
void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
- NetPermissionFlags permissionFlags,
+ NetPermissionFlags permission_flags,
const CAddress& addr_bind,
const CAddress& addr)
{
int nInbound = 0;
int nMaxInbound = nMaxConnections - m_max_outbound;
- AddWhitelistPermissionFlags(permissionFlags, addr);
- if (NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::Implicit)) {
- NetPermissions::ClearFlag(permissionFlags, NetPermissionFlags::Implicit);
- if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::ForceRelay);
- if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::Relay);
- NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::Mempool);
- NetPermissions::AddFlag(permissionFlags, NetPermissionFlags::NoBan);
+ AddWhitelistPermissionFlags(permission_flags, addr);
+ if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::Implicit)) {
+ NetPermissions::ClearFlag(permission_flags, NetPermissionFlags::Implicit);
+ if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permission_flags, NetPermissionFlags::ForceRelay);
+ if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permission_flags, NetPermissionFlags::Relay);
+ NetPermissions::AddFlag(permission_flags, NetPermissionFlags::Mempool);
+ NetPermissions::AddFlag(permission_flags, NetPermissionFlags::NoBan);
}
{
@@ -1207,7 +987,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
// Don't accept connections from banned peers.
bool banned = m_banman && m_banman->IsBanned(addr);
- if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::NoBan) && banned)
+ if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && banned)
{
LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString());
return;
@@ -1215,7 +995,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
// Only accept connections from discouraged peers if our inbound slots aren't (almost) full.
bool discouraged = m_banman && m_banman->IsDiscouraged(addr);
- if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::NoBan) && nInbound + 1 >= nMaxInbound && discouraged)
+ if (!NetPermissions::HasFlag(permission_flags, NetPermissionFlags::NoBan) && nInbound + 1 >= nMaxInbound && discouraged)
{
LogPrint(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToString());
return;
@@ -1234,13 +1014,12 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
ServiceFlags nodeServices = nLocalServices;
- if (NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::BloomFilter)) {
+ if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::BloomFilter)) {
nodeServices = static_cast<ServiceFlags>(nodeServices | NODE_BLOOM);
}
const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
CNode* pnode = new CNode(id,
- nodeServices,
std::move(sock),
addr,
CalculateKeyedNetGroup(addr),
@@ -1248,11 +1027,13 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
addr_bind,
/*addrNameIn=*/"",
ConnectionType::INBOUND,
- inbound_onion);
+ inbound_onion,
+ CNodeOptions{
+ .permission_flags = permission_flags,
+ .prefer_evict = discouraged,
+ });
pnode->AddRef();
- pnode->m_permissionFlags = permissionFlags;
- pnode->m_prefer_evict = discouraged;
- m_msgproc->InitializeNode(pnode);
+ m_msgproc->InitializeNode(*pnode, nodeServices);
LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString());
@@ -1700,9 +1481,8 @@ void CConnman::ThreadDNSAddressSeed()
unsigned int nMaxIPs = 256; // Limits number of IPs learned from a DNS seed
if (LookupHost(host, vIPs, nMaxIPs, true)) {
for (const CNetAddr& ip : vIPs) {
- int nOneDay = 24*3600;
CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
- addr.nTime = GetTime() - 3*nOneDay - rng.randrange(4*nOneDay); // use a random age between 3 and 7 days old
+ addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
vAdd.push_back(addr);
found++;
}
@@ -1720,12 +1500,12 @@ void CConnman::ThreadDNSAddressSeed()
void CConnman::DumpAddresses()
{
- int64_t nStart = GetTimeMillis();
+ const auto start{SteadyClock::now()};
DumpPeerAddresses(::gArgs, addrman);
LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat %dms\n",
- addrman.size(), GetTimeMillis() - nStart);
+ addrman.size(), Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
}
void CConnman::ProcessAddrFetch()
@@ -1799,6 +1579,7 @@ int CConnman::GetExtraBlockRelayCount() const
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
{
SetSyscallSandboxPolicy(SyscallSandboxPolicy::NET_OPEN_CONNECTION);
+ FastRandomContext rng;
// Connect to specific addresses
if (!connect.empty())
{
@@ -1861,15 +1642,28 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
LOCK2(m_addr_fetches_mutex, m_added_nodes_mutex);
if (m_addr_fetches.empty() && m_added_nodes.empty()) {
add_fixed_seeds_now = true;
- LogPrintf("Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n");
+ LogPrintf("Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet), -addnode is not provided and all -seednode(s) attempted\n");
}
}
if (add_fixed_seeds_now) {
+ std::vector<CAddress> seed_addrs{ConvertSeeds(Params().FixedSeeds())};
+ // We will not make outgoing connections to peers that are unreachable
+ // (e.g. because of -onlynet configuration).
+ // Therefore, we do not add them to addrman in the first place.
+ // Note that if you change -onlynet setting from one network to another,
+ // peers.dat will contain only peers of unreachable networks and
+ // manual intervention will be needed (either delete peers.dat after
+ // configuration change or manually add some reachable peer using addnode),
+ // see <https://github.com/bitcoin/bitcoin/issues/26035> for details.
+ seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
+ [](const CAddress& addr) { return !IsReachable(addr); }),
+ seed_addrs.end());
CNetAddr local;
local.SetInternal("fixedseeds");
- addrman.Add(ConvertSeeds(Params().FixedSeeds()), local);
+ addrman.Add(seed_addrs, local);
add_fixed_seeds = false;
+ LogPrintf("Added %d fixed seeds from reachable networks.\n", seed_addrs.size());
}
}
@@ -1967,7 +1761,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
addrman.ResolveCollisions();
- int64_t nANow = GetAdjustedTime();
+ const auto current_time{NodeClock::now()};
int nTries = 0;
while (!interruptNet)
{
@@ -1990,7 +1784,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
break;
CAddress addr;
- int64_t addr_last_try{0};
+ NodeSeconds addr_last_try{0s};
if (fFeeler) {
// First, try to get a tried table collision address. This returns
@@ -2030,8 +1824,9 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
continue;
// only consider very recently tried nodes after 30 failed attempts
- if (nANow - addr_last_try < 600 && nTries < 30)
+ if (current_time - addr_last_try < 10min && nTries < 30) {
continue;
+ }
// for non-feelers, require all the services we'll want,
// for feelers, only require they be a full node (only because most
@@ -2052,12 +1847,11 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
}
if (addrConnect.IsValid()) {
-
if (fFeeler) {
// Add small amount of random noise before connection to avoid synchronization.
- int randsleep = GetRand<int>(FEELER_SLEEP_WINDOW * 1000);
- if (!interruptNet.sleep_for(std::chrono::milliseconds(randsleep)))
+ if (!interruptNet.sleep_for(rng.rand_uniform_duration<CThreadInterrupt::Clock>(FEELER_SLEEP_WINDOW))) {
return;
+ }
LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToString());
}
@@ -2190,7 +1984,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
if (grantOutbound)
grantOutbound->MoveTo(pnode->grantOutbound);
- m_msgproc->InitializeNode(pnode);
+ m_msgproc->InitializeNode(*pnode, nLocalServices);
{
LOCK(m_nodes_mutex);
m_nodes.push_back(pnode);
@@ -2323,8 +2117,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
#endif
}
- if (::bind(sock->Get(), (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
- {
+ if (sock->Bind(reinterpret_cast<struct sockaddr*>(&sockaddr), len) == SOCKET_ERROR) {
int nErr = WSAGetLastError();
if (nErr == WSAEADDRINUSE)
strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME);
@@ -2336,7 +2129,7 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
LogPrintf("Bound to %s\n", addrBind.ToString());
// Listen for incoming connections
- if (listen(sock->Get(), SOMAXCONN) == SOCKET_ERROR)
+ if (sock->Listen(SOMAXCONN) == SOCKET_ERROR)
{
strError = strprintf(_("Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", strError.original);
@@ -2492,7 +2285,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
}
Proxy i2p_sam;
- if (GetProxy(NET_I2P, i2p_sam)) {
+ if (GetProxy(NET_I2P, i2p_sam) && connOptions.m_i2p_accept_incoming) {
m_i2p_sam_session = std::make_unique<i2p::sam::Session>(gArgs.GetDataDirNet() / "i2p_private_key",
i2p_sam.proxy, &interruptNet);
}
@@ -2566,7 +2359,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
// Process messages
threadMessageHandler = std::thread(&util::TraceThread, "msghand", [this] { ThreadMessageHandler(); });
- if (connOptions.m_i2p_accept_incoming && m_i2p_sam_session.get() != nullptr) {
+ if (m_i2p_sam_session) {
threadI2PAcceptIncoming =
std::thread(&util::TraceThread, "i2paccept", [this] { ThreadI2PAcceptIncoming(); });
}
@@ -2935,18 +2728,31 @@ ServiceFlags CConnman::GetLocalServices() const
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
-CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, std::shared_ptr<Sock> sock, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
- : m_sock{sock},
+CNode::CNode(NodeId idIn,
+ std::shared_ptr<Sock> sock,
+ const CAddress& addrIn,
+ uint64_t nKeyedNetGroupIn,
+ uint64_t nLocalHostNonceIn,
+ const CAddress& addrBindIn,
+ const std::string& addrNameIn,
+ ConnectionType conn_type_in,
+ bool inbound_onion,
+ CNodeOptions&& node_opts)
+ : m_deserializer{std::make_unique<V1TransportDeserializer>(V1TransportDeserializer(Params(), idIn, SER_NETWORK, INIT_PROTO_VERSION))},
+ m_serializer{std::make_unique<V1TransportSerializer>(V1TransportSerializer())},
+ m_permission_flags{node_opts.permission_flags},
+ m_sock{sock},
m_connected{GetTime<std::chrono::seconds>()},
- addr(addrIn),
- addrBind(addrBindIn),
+ addr{addrIn},
+ addrBind{addrBindIn},
m_addr_name{addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn},
- m_inbound_onion(inbound_onion),
- nKeyedNetGroup(nKeyedNetGroupIn),
- id(idIn),
- nLocalHostNonce(nLocalHostNonceIn),
- m_conn_type(conn_type_in),
- nLocalServices(nLocalServicesIn)
+ m_inbound_onion{inbound_onion},
+ m_prefer_evict{node_opts.prefer_evict},
+ nKeyedNetGroup{nKeyedNetGroupIn},
+ id{idIn},
+ nLocalHostNonce{nLocalHostNonceIn},
+ m_conn_type{conn_type_in},
+ m_i2p_sam_session{std::move(node_opts.i2p_sam_session)}
{
if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND);
@@ -2959,9 +2765,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, std::shared_ptr<Sock> s
} else {
LogPrint(BCLog::NET, "Added connection peer=%d\n", id);
}
-
- m_deserializer = std::make_unique<V1TransportDeserializer>(V1TransportDeserializer(Params(), id, SER_NETWORK, INIT_PROTO_VERSION));
- m_serializer = std::make_unique<V1TransportSerializer>(V1TransportSerializer());
}
bool CConnman::NodeFullyConnected(const CNode* pnode)
@@ -3055,7 +2858,7 @@ void CaptureMessageToFile(const CAddress& addr,
fs::create_directories(base_path);
fs::path path = base_path / (is_incoming ? "msgs_recv.dat" : "msgs_sent.dat");
- CAutoFile f(fsbridge::fopen(path, "ab"), SER_DISK, CLIENT_VERSION);
+ AutoFile f{fsbridge::fopen(path, "ab")};
ser_writedata64(f, now.count());
f.write(MakeByteSpan(msg_type));
diff --git a/src/net.h b/src/net.h
index bf169649c0..044701a339 100644
--- a/src/net.h
+++ b/src/net.h
@@ -8,7 +8,8 @@
#include <chainparams.h>
#include <common/bloom.h>
-#include <compat.h>
+#include <compat/compat.h>
+#include <node/connection_types.h>
#include <consensus/amount.h>
#include <crypto/siphash.h>
#include <hash.h>
@@ -121,78 +122,6 @@ struct CSerializedNetMsg {
std::string m_type;
};
-/** Different types of connections to a peer. This enum encapsulates the
- * information we have available at the time of opening or accepting the
- * connection. Aside from INBOUND, all types are initiated by us.
- *
- * If adding or removing types, please update CONNECTION_TYPE_DOC in
- * src/rpc/net.cpp and src/qt/rpcconsole.cpp, as well as the descriptions in
- * src/qt/guiutil.cpp and src/bitcoin-cli.cpp::NetinfoRequestHandler. */
-enum class ConnectionType {
- /**
- * Inbound connections are those initiated by a peer. This is the only
- * property we know at the time of connection, until P2P messages are
- * exchanged.
- */
- INBOUND,
-
- /**
- * These are the default connections that we use to connect with the
- * network. There is no restriction on what is relayed; by default we relay
- * blocks, addresses & transactions. We automatically attempt to open
- * MAX_OUTBOUND_FULL_RELAY_CONNECTIONS using addresses from our AddrMan.
- */
- OUTBOUND_FULL_RELAY,
-
-
- /**
- * We open manual connections to addresses that users explicitly requested
- * via the addnode RPC or the -addnode/-connect configuration options. Even if a
- * manual connection is misbehaving, we do not automatically disconnect or
- * add it to our discouragement filter.
- */
- MANUAL,
-
- /**
- * Feeler connections are short-lived connections made to check that a node
- * is alive. They can be useful for:
- * - test-before-evict: if one of the peers is considered for eviction from
- * our AddrMan because another peer is mapped to the same slot in the tried table,
- * evict only if this longer-known peer is offline.
- * - move node addresses from New to Tried table, so that we have more
- * connectable addresses in our AddrMan.
- * Note that in the literature ("Eclipse Attacks on Bitcoin’s Peer-to-Peer Network")
- * only the latter feature is referred to as "feeler connections",
- * although in our codebase feeler connections encompass test-before-evict as well.
- * We make these connections approximately every FEELER_INTERVAL:
- * first we resolve previously found collisions if they exist (test-before-evict),
- * otherwise we connect to a node from the new table.
- */
- FEELER,
-
- /**
- * We use block-relay-only connections to help prevent against partition
- * attacks. By not relaying transactions or addresses, these connections
- * are harder to detect by a third party, thus helping obfuscate the
- * network topology. We automatically attempt to open
- * MAX_BLOCK_RELAY_ONLY_ANCHORS using addresses from our anchors.dat. Then
- * addresses from our AddrMan if MAX_BLOCK_RELAY_ONLY_CONNECTIONS
- * isn't reached yet.
- */
- BLOCK_RELAY,
-
- /**
- * AddrFetch connections are short lived connections used to solicit
- * addresses from peers. These are initiated to addresses submitted via the
- * -seednode command line argument, or under certain conditions when the
- * AddrMan is empty.
- */
- ADDR_FETCH,
-};
-
-/** Convert ConnectionType enum to a string value */
-std::string ConnectionTypeAsString(ConnectionType conn_type);
-
/**
* Look up IP addresses from all interfaces on the machine and add them to the
* list of local addresses to self-advertise.
@@ -215,8 +144,8 @@ enum
};
bool IsPeerAddrLocalGood(CNode *pnode);
-/** Returns a local address that we should advertise to this peer */
-std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode);
+/** Returns a local address that we should advertise to this peer. */
+std::optional<CService> GetLocalAddrForPeer(CNode& node);
/**
* Mark a network as reachable or unreachable (no automatic connects to it)
@@ -234,7 +163,8 @@ void RemoveLocal(const CService& addr);
bool SeenLocal(const CService& addr);
bool IsLocal(const CService& addr);
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = nullptr);
-CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices);
+CService GetLocalAddress(const CNetAddr& addrPeer);
+CService MaybeFlipIPv6toCJDNS(const CService& service);
extern bool fDiscover;
@@ -258,7 +188,6 @@ class CNodeStats
{
public:
NodeId nodeid;
- ServiceFlags nServices;
std::chrono::seconds m_last_send;
std::chrono::seconds m_last_recv;
std::chrono::seconds m_last_tx_time;
@@ -276,7 +205,7 @@ public:
mapMsgTypeSize mapSendBytesPerMsgType;
uint64_t nRecvBytes;
mapMsgTypeSize mapRecvBytesPerMsgType;
- NetPermissionFlags m_permissionFlags;
+ NetPermissionFlags m_permission_flags;
std::chrono::microseconds m_last_ping_time;
std::chrono::microseconds m_min_ping_time;
// Our address, as reported by the peer
@@ -397,13 +326,20 @@ public:
class TransportSerializer {
public:
// prepare message for transport (header construction, error-correction computation, payload encryption, etc.)
- virtual void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) = 0;
+ virtual void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) const = 0;
virtual ~TransportSerializer() {}
};
-class V1TransportSerializer : public TransportSerializer {
+class V1TransportSerializer : public TransportSerializer {
public:
- void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) override;
+ void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) const override;
+};
+
+struct CNodeOptions
+{
+ NetPermissionFlags permission_flags = NetPermissionFlags::None;
+ std::unique_ptr<i2p::sam::Session> i2p_sam_session = nullptr;
+ bool prefer_evict = false;
};
/** Information about a peer */
@@ -413,11 +349,10 @@ class CNode
friend struct ConnmanTestMsg;
public:
- std::unique_ptr<TransportDeserializer> m_deserializer;
- std::unique_ptr<TransportSerializer> m_serializer;
+ const std::unique_ptr<TransportDeserializer> m_deserializer; // Used only by SocketHandler thread
+ const std::unique_ptr<const TransportSerializer> m_serializer;
- NetPermissionFlags m_permissionFlags{NetPermissionFlags::None};
- std::atomic<ServiceFlags> nServices{NODE_NONE};
+ const NetPermissionFlags m_permission_flags;
/**
* Socket used for communication with the node.
@@ -441,7 +376,7 @@ public:
RecursiveMutex cs_vProcessMsg;
std::list<CNetMessage> vProcessMsg GUARDED_BY(cs_vProcessMsg);
- size_t nProcessQueueSize{0};
+ size_t nProcessQueueSize GUARDED_BY(cs_vProcessMsg){0};
RecursiveMutex cs_sendProcessing;
@@ -466,12 +401,10 @@ public:
* from the wire. This cleaned string can safely be logged or displayed.
*/
std::string cleanSubVer GUARDED_BY(m_subver_mutex){};
- bool m_prefer_evict{false}; // This peer is preferred for eviction.
+ const bool m_prefer_evict{false}; // This peer is preferred for eviction.
bool HasPermission(NetPermissionFlags permission) const {
- return NetPermissions::HasFlag(m_permissionFlags, permission);
+ return NetPermissions::HasFlag(m_permission_flags, permission);
}
- bool fClient{false}; // set by version message
- bool m_limited_node{false}; //after BIP159, set by version message
/** fSuccessfullyConnected is set to true on receiving VERACK from the peer. */
std::atomic_bool fSuccessfullyConnected{false};
// Setting fDisconnect to true will cause the node to be disconnected the
@@ -555,6 +488,9 @@ public:
// Peer selected us as (compact blocks) high-bandwidth peer (BIP152)
std::atomic<bool> m_bip152_highbandwidth_from{false};
+ /** Whether this peer provides all services that we want. Used for eviction decisions */
+ std::atomic_bool m_has_all_wanted_services{false};
+
/** Whether we should relay transactions to this peer (their version
* message did not include fRelay=false and this is not a block-relay-only
* connection). This only changes from false to true. It will never change
@@ -585,7 +521,16 @@ public:
* criterium in CConnman::AttemptToEvictConnection. */
std::atomic<std::chrono::microseconds> m_min_ping_time{std::chrono::microseconds::max()};
- CNode(NodeId id, ServiceFlags nLocalServicesIn, std::shared_ptr<Sock> sock, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion);
+ CNode(NodeId id,
+ std::shared_ptr<Sock> sock,
+ const CAddress& addrIn,
+ uint64_t nKeyedNetGroupIn,
+ uint64_t nLocalHostNonceIn,
+ const CAddress& addrBindIn,
+ const std::string& addrNameIn,
+ ConnectionType conn_type_in,
+ bool inbound_onion,
+ CNodeOptions&& node_opts = {});
CNode(const CNode&) = delete;
CNode& operator=(const CNode&) = delete;
@@ -643,11 +588,6 @@ public:
void CopyStats(CNodeStats& stats) EXCLUSIVE_LOCKS_REQUIRED(!m_subver_mutex, !m_addr_local_mutex, !cs_vSend, !cs_vRecv);
- ServiceFlags GetLocalServices() const
- {
- return nLocalServices;
- }
-
std::string ConnectionTypeAsString() const { return ::ConnectionTypeAsString(m_conn_type); }
/** A ping-pong round trip has completed successfully. Update latest and minimum ping times. */
@@ -662,23 +602,6 @@ private:
const ConnectionType m_conn_type;
std::atomic<int> m_greatest_common_version{INIT_PROTO_VERSION};
- //! Services offered to this peer.
- //!
- //! This is supplied by the parent CConnman during peer connection
- //! (CConnman::ConnectNode()) from its attribute of the same name.
- //!
- //! This is const because there is no protocol defined for renegotiating
- //! services initially offered to a peer. The set of local services we
- //! offer should not change after initialization.
- //!
- //! An interesting example of this is NODE_NETWORK and initial block
- //! download: a node which starts up from scratch doesn't have any blocks
- //! to serve, but still advertises NODE_NETWORK because it will eventually
- //! fulfill this role after IBD completes. P2P code is written in such a
- //! way that it can gracefully handle peers who don't make good on their
- //! service advertisements.
- const ServiceFlags nLocalServices;
-
std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread
// Our address, as reported by the peer
@@ -687,6 +610,18 @@ private:
mapMsgTypeSize mapSendBytesPerMsgType GUARDED_BY(cs_vSend);
mapMsgTypeSize mapRecvBytesPerMsgType GUARDED_BY(cs_vRecv);
+
+ /**
+ * If an I2P session is created per connection (for outbound transient I2P
+ * connections) then it is stored here so that it can be destroyed when the
+ * socket is closed. I2P sessions involve a data/transport socket (in `m_sock`)
+ * and a control socket (in `m_i2p_sam_session`). For transient sessions, once
+ * the data socket is closed, the control socket is not going to be used anymore
+ * and is just taking up resources. So better close it as soon as `m_sock` is
+ * closed.
+ * Otherwise this unique_ptr is empty.
+ */
+ std::unique_ptr<i2p::sam::Session> m_i2p_sam_session GUARDED_BY(m_sock_mutex);
};
/**
@@ -696,7 +631,7 @@ class NetEventsInterface
{
public:
/** Initialize a peer (setup state, queue any initial messages) */
- virtual void InitializeNode(CNode* pnode) = 0;
+ virtual void InitializeNode(CNode& node, ServiceFlags our_services) = 0;
/** Handle removal of a peer (clear state) */
virtual void FinalizeNode(const CNode& node) = 0;
@@ -963,12 +898,12 @@ private:
* Create a `CNode` object from a socket that has just been accepted and add the node to
* the `m_nodes` member.
* @param[in] sock Connected socket to communicate with the peer.
- * @param[in] permissionFlags The peer's permissions.
+ * @param[in] permission_flags The peer's permissions.
* @param[in] addr_bind The address and port at our side of the connection.
* @param[in] addr The address and port at the peer's side of the connection.
*/
void CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
- NetPermissionFlags permissionFlags,
+ NetPermissionFlags permission_flags,
const CAddress& addr_bind,
const CAddress& addr);
@@ -1106,16 +1041,14 @@ private:
std::map<uint64_t, CachedAddrResponse> m_addr_response_caches;
/**
- * Services this instance offers.
+ * Services this node offers.
*
- * This data is replicated in each CNode instance we create during peer
- * connection (in ConnectNode()) under a member also called
- * nLocalServices.
+ * This data is replicated in each Peer instance we create.
*
* This data is not marked const, but after being set it should not
- * change. See the note in CNode::nLocalServices documentation.
+ * change.
*
- * \sa CNode::nLocalServices
+ * \sa Peer::our_services
*/
ServiceFlags nLocalServices;
@@ -1165,7 +1098,8 @@ private:
/**
* I2P SAM session.
- * Used to accept incoming and make outgoing I2P connections.
+ * Used to accept incoming and make outgoing I2P connections from a persistent
+ * address.
*/
std::unique_ptr<i2p::sam::Session> m_i2p_sam_session;
@@ -1247,54 +1181,4 @@ extern std::function<void(const CAddress& addr,
bool is_incoming)>
CaptureMessage;
-struct NodeEvictionCandidate
-{
- NodeId id;
- std::chrono::seconds m_connected;
- std::chrono::microseconds m_min_ping_time;
- std::chrono::seconds m_last_block_time;
- std::chrono::seconds m_last_tx_time;
- bool fRelevantServices;
- bool m_relay_txs;
- bool fBloomFilter;
- uint64_t nKeyedNetGroup;
- bool prefer_evict;
- bool m_is_local;
- Network m_network;
-};
-
-/**
- * Select an inbound peer to evict after filtering out (protecting) peers having
- * distinct, difficult-to-forge characteristics. The protection logic picks out
- * fixed numbers of desirable peers per various criteria, followed by (mostly)
- * ratios of desirable or disadvantaged peers. If any eviction candidates
- * remain, the selection logic chooses a peer to evict.
- */
-[[nodiscard]] std::optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates);
-
-/** Protect desirable or disadvantaged inbound peers from eviction by ratio.
- *
- * This function protects half of the peers which have been connected the
- * longest, to replicate the non-eviction implicit behavior and preclude attacks
- * that start later.
- *
- * Half of these protected spots (1/4 of the total) are reserved for the
- * following categories of peers, sorted by longest uptime, even if they're not
- * longest uptime overall:
- *
- * - onion peers connected via our tor control service
- *
- * - localhost peers, as manually configured hidden services not using
- * `-bind=addr[:port]=onion` will not be detected as inbound onion connections
- *
- * - I2P peers
- *
- * - CJDNS peers
- *
- * This helps protect these privacy network peers, which tend to be otherwise
- * disadvantaged under our eviction criteria for their higher min ping times
- * relative to IPv4/IPv6 peers, and favorise the diversity of peer connections.
- */
-void ProtectEvictionCandidatesByRatio(std::vector<NodeEvictionCandidate>& vEvictionCandidates);
-
#endif // BITCOIN_NET_H
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 751a03f01c..3edc051034 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -14,6 +14,7 @@
#include <consensus/validation.h>
#include <deploymentstatus.h>
#include <hash.h>
+#include <headerssync.h>
#include <index/blockfilterindex.h>
#include <merkleblock.h>
#include <netbase.h>
@@ -29,6 +30,7 @@
#include <scheduler.h>
#include <streams.h>
#include <sync.h>
+#include <timedata.h>
#include <tinyformat.h>
#include <txmempool.h>
#include <txorphanage.h>
@@ -61,6 +63,8 @@ static constexpr auto UNCONDITIONAL_RELAY_DELAY = 2min;
* Timeout = base + per_header * (expected number of headers) */
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE = 15min;
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1ms;
+/** How long to wait for a peer to respond to a getheaders request */
+static constexpr auto HEADERS_RESPONSE_TIME{2min};
/** Protect at least this many outbound peers from disconnection due to slow/
* behind headers chain.
*/
@@ -205,6 +209,23 @@ struct Peer {
/** Same id as the CNode object for this peer */
const NodeId m_id{0};
+ /** Services we offered to this peer.
+ *
+ * This is supplied by CConnman during peer initialization. It's const
+ * because there is no protocol defined for renegotiating services
+ * initially offered to a peer. The set of local services we offer should
+ * not change after initialization.
+ *
+ * An interesting example of this is NODE_NETWORK and initial block
+ * download: a node which starts up from scratch doesn't have any blocks
+ * to serve, but still advertises NODE_NETWORK because it will eventually
+ * fulfill this role after IBD completes. P2P code is written in such a
+ * way that it can gracefully handle peers who don't make good on their
+ * service advertisements. */
+ const ServiceFlags m_our_services;
+ /** Services this peer offered to us. */
+ std::atomic<ServiceFlags> m_their_services{NODE_NONE};
+
/** Protects misbehavior data members */
Mutex m_misbehavior_mutex;
/** Accumulated misbehavior score for this peer */
@@ -269,7 +290,7 @@ struct Peer {
* non-wtxid-relay peers, wtxid for wtxid-relay peers). We use the
* mempool to sort transactions in dependency order before relay, so
* this does not have to be sorted. */
- std::set<uint256> m_tx_inventory_to_send;
+ std::set<uint256> m_tx_inventory_to_send GUARDED_BY(m_tx_inventory_mutex);
/** Whether the peer has requested us to send our complete mempool. Only
* permitted if the peer has NetPermissionFlags::Mempool. See BIP35. */
bool m_send_mempool GUARDED_BY(m_tx_inventory_mutex){false};
@@ -350,13 +371,29 @@ struct Peer {
/** Set of txids to reconsider once their parent transactions have been accepted **/
std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
+ /** Whether we've sent this peer a getheaders in response to an inv prior to initial-headers-sync completing */
+ bool m_inv_triggered_getheaders_before_sync{false};
+
/** Protects m_getdata_requests **/
Mutex m_getdata_requests_mutex;
/** Work queue of items requested by this peer **/
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
- Peer(NodeId id)
+ /** Time of the last getheaders message to this peer */
+ NodeClock::time_point m_last_getheaders_timestamp{};
+
+ /** Protects m_headers_sync **/
+ Mutex m_headers_sync_mutex;
+ /** Headers-sync state for this peer (eg for initial sync, or syncing large
+ * reorgs) **/
+ std::unique_ptr<HeadersSyncState> m_headers_sync PT_GUARDED_BY(m_headers_sync_mutex) GUARDED_BY(m_headers_sync_mutex) {};
+
+ /** Whether we've sent our peer a sendheaders message. **/
+ std::atomic<bool> m_sent_sendheaders{false};
+
+ explicit Peer(NodeId id, ServiceFlags our_services)
: m_id{id}
+ , m_our_services{our_services}
{}
private:
@@ -405,8 +442,6 @@ struct CNodeState {
bool m_requested_hb_cmpctblocks{false};
/** Whether this peer will send us cmpctblocks if we request them. */
bool m_provides_cmpctblocks{false};
- //! Whether this peer can give us witnesses
- bool fHaveWitness{false};
/** State used to enforce CHAIN_SYNC_TIMEOUT and EXTRA_PEER_CHECK_INTERVAL logic.
*
@@ -477,31 +512,32 @@ public:
EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex);
/** Implement NetEventsInterface */
- void InitializeNode(CNode* pnode) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
- void FinalizeNode(const CNode& node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
+ void InitializeNode(CNode& node, ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
+ void FinalizeNode(const CNode& node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex);
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override
- EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex);
+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex);
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing)
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex);
/** Implement PeerManager */
void StartScheduledTasks(CScheduler& scheduler) override;
void CheckForStaleTipAndEvictPeers() override;
- std::optional<std::string> FetchBlock(NodeId peer_id, const CBlockIndex& block_index) override;
+ std::optional<std::string> FetchBlock(NodeId peer_id, const CBlockIndex& block_index) override
+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; }
void SendPings() override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void RelayTransaction(const uint256& txid, const uint256& wtxid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void SetBestHeight(int height) override { m_best_height = height; };
- void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
+ void UnitTestMisbehaving(NodeId peer_id, int howmuch) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex) { Misbehaving(*Assert(GetPeerRef(peer_id)), howmuch, ""); };
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) override
- EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex);
+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex);
void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds) override;
private:
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
- void ConsiderEviction(CNode& pto, std::chrono::seconds time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */
void EvictExtraOutboundPeers(std::chrono::seconds now) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -518,6 +554,12 @@ private:
PeerRef RemovePeer(NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/**
+ * Increment peer's misbehavior score. If the new value >= DISCOURAGEMENT_THRESHOLD, mark the node
+ * to be discouraged, meaning the peer might be disconnected and added to the discouragement filter.
+ */
+ void Misbehaving(Peer& peer, int howmuch, const std::string& message);
+
+ /**
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
*
* @param[in] via_compact_block this bool is passed in because net_processing should
@@ -549,14 +591,81 @@ private:
void ProcessOrphanTx(std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
- /** Process a single headers message from a peer. */
- void ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
- const std::vector<CBlockHeader>& headers,
+ /** Process a single headers message from a peer.
+ *
+ * @param[in] pfrom CNode of the peer
+ * @param[in] peer The peer sending us the headers
+ * @param[in] headers The headers received. Note that this may be modified within ProcessHeadersMessage.
+ * @param[in] via_compact_block Whether this header came in via compact block handling.
+ */
+ void ProcessHeadersMessage(CNode& pfrom, Peer& peer,
+ std::vector<CBlockHeader>&& headers,
bool via_compact_block)
- EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
+ EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex);
+ /** Various helpers for headers processing, invoked by ProcessHeadersMessage() */
+ /** Return true if headers are continuous and have valid proof-of-work (DoS points assigned on failure) */
+ bool CheckHeadersPoW(const std::vector<CBlockHeader>& headers, const Consensus::Params& consensusParams, Peer& peer);
+ /** Calculate an anti-DoS work threshold for headers chains */
+ arith_uint256 GetAntiDoSWorkThreshold();
+ /** Deal with state tracking and headers sync for peers that send the
+ * occasional non-connecting header (this can happen due to BIP 130 headers
+ * announcements for blocks interacting with the 2hr (MAX_FUTURE_BLOCK_TIME) rule). */
+ void HandleFewUnconnectingHeaders(CNode& pfrom, Peer& peer, const std::vector<CBlockHeader>& headers);
+ /** Return true if the headers connect to each other, false otherwise */
+ bool CheckHeadersAreContinuous(const std::vector<CBlockHeader>& headers) const;
+ /** Try to continue a low-work headers sync that has already begun.
+ * Assumes the caller has already verified the headers connect, and has
+ * checked that each header satisfies the proof-of-work target included in
+ * the header.
+ * @param[in] peer The peer we're syncing with.
+ * @param[in] pfrom CNode of the peer
+ * @param[in,out] headers The headers to be processed.
+ * @return True if the passed in headers were successfully processed
+ * as the continuation of a low-work headers sync in progress;
+ * false otherwise.
+ * If false, the passed in headers will be returned back to
+ * the caller.
+ * If true, the returned headers may be empty, indicating
+ * there is no more work for the caller to do; or the headers
+ * may be populated with entries that have passed anti-DoS
+ * checks (and therefore may be validated for block index
+ * acceptance by the caller).
+ */
+ bool IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom,
+ std::vector<CBlockHeader>& headers)
+ EXCLUSIVE_LOCKS_REQUIRED(peer.m_headers_sync_mutex, !m_headers_presync_mutex);
+ /** Check work on a headers chain to be processed, and if insufficient,
+ * initiate our anti-DoS headers sync mechanism.
+ *
+ * @param[in] peer The peer whose headers we're processing.
+ * @param[in] pfrom CNode of the peer
+ * @param[in] chain_start_header Where these headers connect in our index.
+ * @param[in,out] headers The headers to be processed.
+ *
+ * @return True if chain was low work and a headers sync was
+ * initiated (and headers will be empty after calling); false
+ * otherwise.
+ */
+ bool TryLowWorkHeadersSync(Peer& peer, CNode& pfrom,
+ const CBlockIndex* chain_start_header,
+ std::vector<CBlockHeader>& headers)
+ EXCLUSIVE_LOCKS_REQUIRED(!peer.m_headers_sync_mutex, !m_peer_mutex, !m_headers_presync_mutex);
+
+ /** Return true if the given header is an ancestor of
+ * m_chainman.m_best_header or our current tip */
+ bool IsAncestorOfBestHeaderOrTip(const CBlockIndex* header) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+
+ /** Request further headers from this peer with a given locator.
+ * We don't issue a getheaders message if we have a recent one outstanding.
+ * This returns true if a getheaders is actually sent, and false otherwise.
+ */
+ bool MaybeSendGetHeaders(CNode& pfrom, const CBlockLocator& locator, Peer& peer);
+ /** Potentially fetch blocks from this peer upon receipt of a new headers tip */
+ void HeadersDirectFetchBlocks(CNode& pfrom, const Peer& peer, const CBlockIndex* pindexLast);
+ /** Update peer state based on received headers message */
+ void UpdatePeerStateForReceivedHeaders(CNode& pfrom, const CBlockIndex *pindexLast, bool received_new_header, bool may_have_more_headers);
- void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req)
- EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
+ void SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req);
/** Register with TxRequestTracker that an INV has been received from a
* peer. The announcement parameters are decided in PeerManager and then
@@ -576,6 +685,9 @@ private:
/** Send `addr` messages on a regular schedule. */
void MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time);
+ /** Send a single `sendheaders` message, after we have completed headers sync with a peer. */
+ void MaybeSendSendHeaders(CNode& node, Peer& peer);
+
/** Relay (gossip) an address to a few randomly chosen nodes.
*
* @param[in] originator The id of the peer that sent us the address. We don't want to relay it back.
@@ -601,7 +713,7 @@ private:
std::atomic<int> m_best_height{-1};
/** Next time to check for stale tip */
- std::chrono::seconds m_stale_tip_check_time{0s};
+ std::chrono::seconds m_stale_tip_check_time GUARDED_BY(cs_main){0s};
/** Whether this node is running in -blocksonly mode */
const bool m_ignore_incoming_txs;
@@ -610,7 +722,7 @@ private:
/** Whether we've completed initial sync yet, for determining when to turn
* on extra block-relay-only peers. */
- bool m_initial_sync_finished{false};
+ bool m_initial_sync_finished GUARDED_BY(cs_main){false};
/** Protects m_peer_map. This mutex must not be locked while holding a lock
* on any of the mutexes inside a Peer object. */
@@ -631,13 +743,16 @@ private:
/** Get a pointer to a mutable CNodeState. */
CNodeState* State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- uint32_t GetFetchFlags(const CNode& pfrom) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ uint32_t GetFetchFlags(const Peer& peer) const;
std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
/** Number of nodes with fSyncStarted. */
int nSyncStarted GUARDED_BY(cs_main) = 0;
+ /** Hash of the last block we received via INV */
+ uint256 m_last_block_inv_triggering_headers_sync{};
+
/**
* Sources of received blocks, saved to be able punish them when processing
* happens afterwards.
@@ -729,6 +844,24 @@ private:
std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block GUARDED_BY(m_most_recent_block_mutex);
uint256 m_most_recent_block_hash GUARDED_BY(m_most_recent_block_mutex);
+ // Data about the low-work headers synchronization, aggregated from all peers' HeadersSyncStates.
+ /** Mutex guarding the other m_headers_presync_* variables. */
+ Mutex m_headers_presync_mutex;
+ /** A type to represent statistics about a peer's low-work headers sync.
+ *
+ * - The first field is the total verified amount of work in that synchronization.
+ * - The second is:
+ * - nullopt: the sync is in REDOWNLOAD phase (phase 2).
+ * - {height, timestamp}: the sync has the specified tip height and block timestamp (phase 1).
+ */
+ using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
+ /** Statistics for all peers in low-work headers sync. */
+ std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats GUARDED_BY(m_headers_presync_mutex) {};
+ /** The peer with the most-work entry in m_headers_presync_stats. */
+ NodeId m_headers_presync_bestpeer GUARDED_BY(m_headers_presync_mutex) {-1};
+ /** The m_headers_presync_stats improved, and needs signalling. */
+ std::atomic_bool m_headers_presync_should_signal{false};
+
/** Height of the highest block announced using BIP 152 high-bandwidth mode. */
int m_highest_fast_announce{0};
@@ -752,7 +885,7 @@ private:
/** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has
* at most count entries.
*/
- void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void FindNextBlocksToDownload(const Peer& peer, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> > mapBlocksInFlight GUARDED_BY(cs_main);
@@ -766,7 +899,7 @@ private:
EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex, peer.m_getdata_requests_mutex) LOCKS_EXCLUDED(::cs_main);
/** Process a new block. Perform any post-processing housekeeping */
- void ProcessBlock(CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing);
+ void ProcessBlock(CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing, bool min_pow_checked);
/** Relay map (txid or wtxid -> CTransactionRef) */
typedef std::map<uint256, CTransactionRef> MapRelay;
@@ -822,6 +955,7 @@ private:
*
* May disconnect from the peer in the case of a bad request.
*
+ * @param[in] node The node that we received the request from
* @param[in] peer The peer that we received the request from
* @param[in] filter_type The filter type the request is for. Must be basic filters.
* @param[in] start_height The start height for the request
@@ -831,7 +965,7 @@ private:
* @param[out] filter_index The filter index, if the request can be serviced.
* @return True if the request can be serviced.
*/
- bool PrepareBlockFilterRequest(CNode& peer,
+ bool PrepareBlockFilterRequest(CNode& node, Peer& peer,
BlockFilterType filter_type, uint32_t start_height,
const uint256& stop_hash, uint32_t max_height_diff,
const CBlockIndex*& stop_index,
@@ -842,30 +976,33 @@ private:
*
* May disconnect from the peer in the case of a bad request.
*
+ * @param[in] node The node that we received the request from
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
*/
- void ProcessGetCFilters(CNode& peer, CDataStream& vRecv);
+ void ProcessGetCFilters(CNode& node, Peer& peer, CDataStream& vRecv);
/**
* Handle a cfheaders request.
*
* May disconnect from the peer in the case of a bad request.
*
+ * @param[in] node The node that we received the request from
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
*/
- void ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv);
+ void ProcessGetCFHeaders(CNode& node, Peer& peer, CDataStream& vRecv);
/**
* Handle a getcfcheckpt request.
*
* May disconnect from the peer in the case of a bad request.
*
+ * @param[in] node The node that we received the request from
* @param[in] peer The peer that we received the request from
* @param[in] vRecv The raw message received
*/
- void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv);
+ void ProcessGetCFCheckPt(CNode& node, Peer& peer, CDataStream& vRecv);
/** Checks if address relay is permitted with peer. If needed, initializes
* the m_addr_known bloom filter and sets m_addr_relay_enabled to true.
@@ -929,6 +1066,26 @@ static void AddKnownTx(Peer& peer, const uint256& hash)
tx_relay->m_tx_inventory_known_filter.insert(hash);
}
+/** Whether this peer can serve us blocks. */
+static bool CanServeBlocks(const Peer& peer)
+{
+ return peer.m_their_services & (NODE_NETWORK|NODE_NETWORK_LIMITED);
+}
+
+/** Whether this peer can only serve limited recent blocks (e.g. because
+ * it prunes old blocks) */
+static bool IsLimitedPeer(const Peer& peer)
+{
+ return (!(peer.m_their_services & NODE_NETWORK) &&
+ (peer.m_their_services & NODE_NETWORK_LIMITED));
+}
+
+/** Whether this peer can serve us witness data */
+static bool CanServeWitnesses(const Peer& peer)
+{
+ return peer.m_their_services & NODE_WITNESS;
+}
+
std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
std::chrono::seconds average_interval)
{
@@ -1077,7 +1234,7 @@ bool PeerManagerImpl::TipMayBeStale()
bool PeerManagerImpl::CanDirectFetch()
{
- return m_chainman.ActiveChain().Tip()->GetBlockTime() > GetAdjustedTime() - m_chainparams.GetConsensus().nPowTargetSpacing * 20;
+ return m_chainman.ActiveChain().Tip()->Time() > GetAdjustedTime() - m_chainparams.GetConsensus().PowTargetSpacing() * 20;
}
static bool PeerHasHeader(CNodeState *state, const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
@@ -1122,17 +1279,17 @@ void PeerManagerImpl::UpdateBlockAvailability(NodeId nodeid, const uint256 &hash
}
}
-void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller)
+void PeerManagerImpl::FindNextBlocksToDownload(const Peer& peer, unsigned int count, std::vector<const CBlockIndex*>& vBlocks, NodeId& nodeStaller)
{
if (count == 0)
return;
vBlocks.reserve(vBlocks.size() + count);
- CNodeState *state = State(nodeid);
+ CNodeState *state = State(peer.m_id);
assert(state != nullptr);
// Make sure pindexBestKnownBlock is up to date, we'll need it.
- ProcessBlockAvailability(nodeid);
+ ProcessBlockAvailability(peer.m_id);
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.ActiveChain().Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
// This peer has nothing interesting.
@@ -1180,7 +1337,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
// We consider the chain that this peer is on invalid.
return;
}
- if (!State(nodeid)->fHaveWitness && DeploymentActiveAt(*pindex, m_chainman, Consensus::DEPLOYMENT_SEGWIT)) {
+ if (!CanServeWitnesses(peer) && DeploymentActiveAt(*pindex, m_chainman, Consensus::DEPLOYMENT_SEGWIT)) {
// We wouldn't download this block or its descendants from this peer.
return;
}
@@ -1191,7 +1348,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
// The block is not already downloaded, and not yet in flight.
if (pindex->nHeight > nWindowEnd) {
// We reached the end of the window.
- if (vBlocks.size() == 0 && waitingfor != nodeid) {
+ if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
// We aren't able to fetch anything, but we would be if the download window was one larger.
nodeStaller = waitingfor;
}
@@ -1213,10 +1370,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(NodeId nodeid, unsigned int count
void PeerManagerImpl::PushNodeVersion(CNode& pnode, const Peer& peer)
{
- // Note that pnode->GetLocalServices() is a reflection of the local
- // services we were offering when the CNode object was created for this
- // peer.
- uint64_t my_services{pnode.GetLocalServices()};
+ uint64_t my_services{peer.m_our_services};
const int64_t nTime{count_seconds(GetTime<std::chrono::seconds>())};
uint64_t nonce = pnode.GetLocalNonce();
const int nNodeStartingHeight{m_best_height};
@@ -1273,21 +1427,21 @@ void PeerManagerImpl::UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_s
if (state) state->m_last_block_announcement = time_in_seconds;
}
-void PeerManagerImpl::InitializeNode(CNode *pnode)
+void PeerManagerImpl::InitializeNode(CNode& node, ServiceFlags our_services)
{
- NodeId nodeid = pnode->GetId();
+ NodeId nodeid = node.GetId();
{
LOCK(cs_main);
- m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(pnode->IsInboundConn()));
+ m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(node.IsInboundConn()));
assert(m_txrequest.Count(nodeid) == 0);
}
- PeerRef peer = std::make_shared<Peer>(nodeid);
+ PeerRef peer = std::make_shared<Peer>(nodeid, our_services);
{
LOCK(m_peer_mutex);
m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
}
- if (!pnode->IsInboundConn()) {
- PushNodeVersion(*pnode, *peer);
+ if (!node.IsInboundConn()) {
+ PushNodeVersion(node, *peer);
}
}
@@ -1366,6 +1520,10 @@ void PeerManagerImpl::FinalizeNode(const CNode& node)
// fSuccessfullyConnected set.
m_addrman.Connected(node.addr);
}
+ {
+ LOCK(m_headers_presync_mutex);
+ m_headers_presync_stats.erase(nodeid);
+ }
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
}
@@ -1405,6 +1563,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
PeerRef peer = GetPeerRef(nodeid);
if (peer == nullptr) return false;
+ stats.their_services = peer->m_their_services;
stats.m_starting_height = peer->m_starting_height;
// It is common for nodes with good ping times to suddenly become lagged,
// due to a new block arriving or other large transfer.
@@ -1429,6 +1588,12 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
stats.m_addr_processed = peer->m_addr_processed.load();
stats.m_addr_rate_limited = peer->m_addr_rate_limited.load();
stats.m_addr_relay_enabled = peer->m_addr_relay_enabled.load();
+ {
+ LOCK(peer->m_headers_sync_mutex);
+ if (peer->m_headers_sync) {
+ stats.presync_height = peer->m_headers_sync->GetPresyncHeight();
+ }
+ }
return true;
}
@@ -1444,41 +1609,43 @@ void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx)
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % max_extra_txn;
}
-void PeerManagerImpl::Misbehaving(const NodeId pnode, const int howmuch, const std::string& message)
+void PeerManagerImpl::Misbehaving(Peer& peer, int howmuch, const std::string& message)
{
assert(howmuch > 0);
- PeerRef peer = GetPeerRef(pnode);
- if (peer == nullptr) return;
-
- LOCK(peer->m_misbehavior_mutex);
- const int score_before{peer->m_misbehavior_score};
- peer->m_misbehavior_score += howmuch;
- const int score_now{peer->m_misbehavior_score};
+ LOCK(peer.m_misbehavior_mutex);
+ const int score_before{peer.m_misbehavior_score};
+ peer.m_misbehavior_score += howmuch;
+ const int score_now{peer.m_misbehavior_score};
const std::string message_prefixed = message.empty() ? "" : (": " + message);
std::string warning;
if (score_now >= DISCOURAGEMENT_THRESHOLD && score_before < DISCOURAGEMENT_THRESHOLD) {
warning = " DISCOURAGE THRESHOLD EXCEEDED";
- peer->m_should_discourage = true;
+ peer.m_should_discourage = true;
}
LogPrint(BCLog::NET, "Misbehaving: peer=%d (%d -> %d)%s%s\n",
- pnode, score_before, score_now, warning, message_prefixed);
+ peer.m_id, score_before, score_now, warning, message_prefixed);
}
bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,
bool via_compact_block, const std::string& message)
{
+ PeerRef peer{GetPeerRef(nodeid)};
switch (state.GetResult()) {
case BlockValidationResult::BLOCK_RESULT_UNSET:
break;
+ case BlockValidationResult::BLOCK_HEADER_LOW_WORK:
+ // We didn't try to process the block because the header chain may have
+ // too little work.
+ break;
// The node is providing invalid data:
case BlockValidationResult::BLOCK_CONSENSUS:
case BlockValidationResult::BLOCK_MUTATED:
if (!via_compact_block) {
- Misbehaving(nodeid, 100, message);
+ if (peer) Misbehaving(*peer, 100, message);
return true;
}
break;
@@ -1493,7 +1660,7 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
// Discourage outbound (but not inbound) peers if on an invalid chain.
// Exempt HB compact block peers. Manual connections are always protected from discouragement.
if (!via_compact_block && !node_state->m_is_inbound) {
- Misbehaving(nodeid, 100, message);
+ if (peer) Misbehaving(*peer, 100, message);
return true;
}
break;
@@ -1501,12 +1668,12 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
case BlockValidationResult::BLOCK_INVALID_HEADER:
case BlockValidationResult::BLOCK_CHECKPOINT:
case BlockValidationResult::BLOCK_INVALID_PREV:
- Misbehaving(nodeid, 100, message);
+ if (peer) Misbehaving(*peer, 100, message);
return true;
// Conflicting (but not necessarily invalid) data or different policy:
case BlockValidationResult::BLOCK_MISSING_PREV:
// TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
- Misbehaving(nodeid, 10, message);
+ if (peer) Misbehaving(*peer, 10, message);
return true;
case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
case BlockValidationResult::BLOCK_TIME_FUTURE:
@@ -1520,12 +1687,13 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
bool PeerManagerImpl::MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message)
{
+ PeerRef peer{GetPeerRef(nodeid)};
switch (state.GetResult()) {
case TxValidationResult::TX_RESULT_UNSET:
break;
// The node is providing invalid data:
case TxValidationResult::TX_CONSENSUS:
- Misbehaving(nodeid, 100, message);
+ if (peer) Misbehaving(*peer, 100, message);
return true;
// Conflicting (but not necessarily invalid) data or different policy:
case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE:
@@ -1560,12 +1728,14 @@ std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const CBl
if (fImporting) return "Importing...";
if (fReindex) return "Reindexing...";
- LOCK(cs_main);
// Ensure this peer exists and hasn't been disconnected
- CNodeState* state = State(peer_id);
- if (state == nullptr) return "Peer does not exist";
+ PeerRef peer = GetPeerRef(peer_id);
+ if (peer == nullptr) return "Peer does not exist";
+
// Ignore pre-segwit peers
- if (!state->fHaveWitness) return "Pre-SegWit peer";
+ if (!CanServeWitnesses(*peer)) return "Pre-SegWit peer";
+
+ LOCK(cs_main);
// Mark block as in-flight unless it already is (for this peer).
// If a block was already in-flight for a different peer, its BLOCKTXN
@@ -1837,8 +2007,15 @@ void PeerManagerImpl::RelayTransaction(const uint256& txid, const uint256& wtxid
auto tx_relay = peer.GetTxRelay();
if (!tx_relay) continue;
- const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
LOCK(tx_relay->m_tx_inventory_mutex);
+ // Only queue transactions for announcement once the version handshake
+ // is completed. The time of arrival for these transactions is
+ // otherwise at risk of leaking to a spy, if the spy is able to
+ // distinguish transactions received during the handshake from the rest
+ // in the announcement.
+ if (tx_relay->m_next_inv_send_time == 0s) continue;
+
+ const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
tx_relay->m_tx_inventory_to_send.insert(hash);
}
@@ -1949,7 +2126,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
}
// Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold
if (!pfrom.HasPermission(NetPermissionFlags::NoBan) && (
- (((pfrom.GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom.GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (m_chainman.ActiveChain().Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) )
+ (((peer.m_our_services & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((peer.m_our_services & NODE_NETWORK) != NODE_NETWORK) && (m_chainman.ActiveChain().Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) )
)) {
LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.GetId());
//disconnect node and prevent it from stalling (would otherwise wait for the missing block)
@@ -2166,21 +2343,21 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
}
}
-uint32_t PeerManagerImpl::GetFetchFlags(const CNode& pfrom) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+uint32_t PeerManagerImpl::GetFetchFlags(const Peer& peer) const
{
uint32_t nFetchFlags = 0;
- if (State(pfrom.GetId())->fHaveWitness) {
+ if (CanServeWitnesses(peer)) {
nFetchFlags |= MSG_WITNESS_FLAG;
}
return nFetchFlags;
}
-void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req)
+void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, Peer& peer, const CBlock& block, const BlockTransactionsRequest& req)
{
BlockTransactions resp(req);
for (size_t i = 0; i < req.indexes.size(); i++) {
if (req.indexes[i] >= block.vtx.size()) {
- Misbehaving(pfrom.GetId(), 100, "getblocktxn with out-of-bounds tx indices");
+ Misbehaving(peer, 100, "getblocktxn with out-of-bounds tx indices");
return;
}
resp.txn[i] = block.vtx[req.indexes[i]];
@@ -2190,192 +2367,523 @@ void PeerManagerImpl::SendBlockTransactions(CNode& pfrom, const CBlock& block, c
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCKTXN, resp));
}
-void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
- const std::vector<CBlockHeader>& headers,
- bool via_compact_block)
+bool PeerManagerImpl::CheckHeadersPoW(const std::vector<CBlockHeader>& headers, const Consensus::Params& consensusParams, Peer& peer)
+{
+ // Do these headers have proof-of-work matching what's claimed?
+ if (!HasValidProofOfWork(headers, consensusParams)) {
+ Misbehaving(peer, 100, "header with invalid proof of work");
+ return false;
+ }
+
+ // Are these headers connected to each other?
+ if (!CheckHeadersAreContinuous(headers)) {
+ Misbehaving(peer, 20, "non-continuous headers sequence");
+ return false;
+ }
+ return true;
+}
+
+arith_uint256 PeerManagerImpl::GetAntiDoSWorkThreshold()
+{
+ arith_uint256 near_chaintip_work = 0;
+ LOCK(cs_main);
+ if (m_chainman.ActiveChain().Tip() != nullptr) {
+ const CBlockIndex *tip = m_chainman.ActiveChain().Tip();
+ // Use a 144 block buffer, so that we'll accept headers that fork from
+ // near our tip.
+ near_chaintip_work = tip->nChainWork - std::min<arith_uint256>(144*GetBlockProof(*tip), tip->nChainWork);
+ }
+ return std::max(near_chaintip_work, arith_uint256(nMinimumChainWork));
+}
+
+/**
+ * Special handling for unconnecting headers that might be part of a block
+ * announcement.
+ *
+ * We'll send a getheaders message in response to try to connect the chain.
+ *
+ * The peer can send up to MAX_UNCONNECTING_HEADERS in a row that
+ * don't connect before given DoS points.
+ *
+ * Once a headers message is received that is valid and does connect,
+ * nUnconnectingHeaders gets reset back to 0.
+ */
+void PeerManagerImpl::HandleFewUnconnectingHeaders(CNode& pfrom, Peer& peer,
+ const std::vector<CBlockHeader>& headers)
{
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
- size_t nCount = headers.size();
- if (nCount == 0) {
- // Nothing interesting. Stop asking this peers for more headers.
- return;
+ LOCK(cs_main);
+ CNodeState *nodestate = State(pfrom.GetId());
+
+ nodestate->nUnconnectingHeaders++;
+ // Try to fill in the missing headers.
+ if (MaybeSendGetHeaders(pfrom, GetLocator(m_chainman.m_best_header), peer)) {
+ LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
+ headers[0].GetHash().ToString(),
+ headers[0].hashPrevBlock.ToString(),
+ m_chainman.m_best_header->nHeight,
+ pfrom.GetId(), nodestate->nUnconnectingHeaders);
+ }
+ // Set hashLastUnknownBlock for this peer, so that if we
+ // eventually get the headers - even from a different peer -
+ // we can use this peer to download.
+ UpdateBlockAvailability(pfrom.GetId(), headers.back().GetHash());
+
+ // The peer may just be broken, so periodically assign DoS points if this
+ // condition persists.
+ if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
+ Misbehaving(peer, 20, strprintf("%d non-connecting headers", nodestate->nUnconnectingHeaders));
}
+}
- bool received_new_header = false;
- const CBlockIndex *pindexLast = nullptr;
- {
- LOCK(cs_main);
- CNodeState *nodestate = State(pfrom.GetId());
+bool PeerManagerImpl::CheckHeadersAreContinuous(const std::vector<CBlockHeader>& headers) const
+{
+ uint256 hashLastBlock;
+ for (const CBlockHeader& header : headers) {
+ if (!hashLastBlock.IsNull() && header.hashPrevBlock != hashLastBlock) {
+ return false;
+ }
+ hashLastBlock = header.GetHash();
+ }
+ return true;
+}
- // If this looks like it could be a block announcement (nCount <
- // MAX_BLOCKS_TO_ANNOUNCE), use special logic for handling headers that
- // don't connect:
- // - Send a getheaders message in response to try to connect the chain.
- // - The peer can send up to MAX_UNCONNECTING_HEADERS in a row that
- // don't connect before giving DoS points
- // - Once a headers message is received that is valid and does connect,
- // nUnconnectingHeaders gets reset back to 0.
- if (!m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
- nodestate->nUnconnectingHeaders++;
- m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), uint256()));
- LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
- headers[0].GetHash().ToString(),
- headers[0].hashPrevBlock.ToString(),
- m_chainman.m_best_header->nHeight,
- pfrom.GetId(), nodestate->nUnconnectingHeaders);
- // Set hashLastUnknownBlock for this peer, so that if we
- // eventually get the headers - even from a different peer -
- // we can use this peer to download.
- UpdateBlockAvailability(pfrom.GetId(), headers.back().GetHash());
-
- if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
- Misbehaving(pfrom.GetId(), 20, strprintf("%d non-connecting headers", nodestate->nUnconnectingHeaders));
+bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom, std::vector<CBlockHeader>& headers)
+{
+ if (peer.m_headers_sync) {
+ auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == MAX_HEADERS_RESULTS);
+ if (result.request_more) {
+ auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
+ // If we were instructed to ask for a locator, it should not be empty.
+ Assume(!locator.vHave.empty());
+ if (!locator.vHave.empty()) {
+ // It should be impossible for the getheaders request to fail,
+ // because we should have cleared the last getheaders timestamp
+ // when processing the headers that triggered this call. But
+ // it may be possible to bypass this via compactblock
+ // processing, so check the result before logging just to be
+ // safe.
+ bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
+ if (sent_getheaders) {
+ LogPrint(BCLog::NET, "more getheaders (from %s) to peer=%d\n",
+ locator.vHave.front().ToString(), pfrom.GetId());
+ } else {
+ LogPrint(BCLog::NET, "error sending next getheaders (from %s) to continue sync with peer=%d\n",
+ locator.vHave.front().ToString(), pfrom.GetId());
+ }
}
- return;
}
- uint256 hashLastBlock;
- for (const CBlockHeader& header : headers) {
- if (!hashLastBlock.IsNull() && header.hashPrevBlock != hashLastBlock) {
- Misbehaving(pfrom.GetId(), 20, "non-continuous headers sequence");
- return;
+ if (peer.m_headers_sync->GetState() == HeadersSyncState::State::FINAL) {
+ peer.m_headers_sync.reset(nullptr);
+
+ // Delete this peer's entry in m_headers_presync_stats.
+ // If this is m_headers_presync_bestpeer, it will be replaced later
+ // by the next peer that triggers the else{} branch below.
+ LOCK(m_headers_presync_mutex);
+ m_headers_presync_stats.erase(pfrom.GetId());
+ } else {
+ // Build statistics for this peer's sync.
+ HeadersPresyncStats stats;
+ stats.first = peer.m_headers_sync->GetPresyncWork();
+ if (peer.m_headers_sync->GetState() == HeadersSyncState::State::PRESYNC) {
+ stats.second = {peer.m_headers_sync->GetPresyncHeight(),
+ peer.m_headers_sync->GetPresyncTime()};
+ }
+
+ // Update statistics in stats.
+ LOCK(m_headers_presync_mutex);
+ m_headers_presync_stats[pfrom.GetId()] = stats;
+ auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
+ bool best_updated = false;
+ if (best_it == m_headers_presync_stats.end()) {
+ // If the cached best peer is outdated, iterate over all remaining ones (including
+ // newly updated one) to find the best one.
+ NodeId peer_best{-1};
+ const HeadersPresyncStats* stat_best{nullptr};
+ for (const auto& [peer, stat] : m_headers_presync_stats) {
+ if (!stat_best || stat > *stat_best) {
+ peer_best = peer;
+ stat_best = &stat;
+ }
+ }
+ m_headers_presync_bestpeer = peer_best;
+ best_updated = (peer_best == pfrom.GetId());
+ } else if (best_it->first == pfrom.GetId() || stats > best_it->second) {
+ // pfrom was and remains the best peer, or pfrom just became best.
+ m_headers_presync_bestpeer = pfrom.GetId();
+ best_updated = true;
+ }
+ if (best_updated && stats.second.has_value()) {
+ // If the best peer updated, and it is in its first phase, signal.
+ m_headers_presync_should_signal = true;
}
- hashLastBlock = header.GetHash();
}
- // If we don't have the last header, then they'll have given us
- // something new (if these headers are valid).
- if (!m_chainman.m_blockman.LookupBlockIndex(hashLastBlock)) {
- received_new_header = true;
+ if (result.success) {
+ // We only overwrite the headers passed in if processing was
+ // successful.
+ headers.swap(result.pow_validated_headers);
}
+
+ return result.success;
}
+ // Either we didn't have a sync in progress, or something went wrong
+ // processing these headers, or we are returning headers to the caller to
+ // process.
+ return false;
+}
- BlockValidationState state;
- if (!m_chainman.ProcessNewBlockHeaders(headers, state, &pindexLast)) {
- if (state.IsInvalid()) {
- MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
- return;
+bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer, CNode& pfrom, const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
+{
+ // Calculate the total work on this chain.
+ arith_uint256 total_work = chain_start_header->nChainWork + CalculateHeadersWork(headers);
+
+ // Our dynamic anti-DoS threshold (minimum work required on a headers chain
+ // before we'll store it)
+ arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
+
+ // Avoid DoS via low-difficulty-headers by only processing if the headers
+ // are part of a chain with sufficient work.
+ if (total_work < minimum_chain_work) {
+ // Only try to sync with this peer if their headers message was full;
+ // otherwise they don't have more headers after this so no point in
+ // trying to sync their too-little-work chain.
+ if (headers.size() == MAX_HEADERS_RESULTS) {
+ // Note: we could advance to the last header in this set that is
+ // known to us, rather than starting at the first header (which we
+ // may already have); however this is unlikely to matter much since
+ // ProcessHeadersMessage() already handles the case where all
+ // headers in a received message are already known and are
+ // ancestors of m_best_header or chainActive.Tip(), by skipping
+ // this logic in that case. So even if the first header in this set
+ // of headers is known, some header in this set must be new, so
+ // advancing to the first unknown header would be a small effect.
+ LOCK(peer.m_headers_sync_mutex);
+ peer.m_headers_sync.reset(new HeadersSyncState(peer.m_id, m_chainparams.GetConsensus(),
+ chain_start_header, minimum_chain_work));
+
+ // Now a HeadersSyncState object for tracking this synchronization is created,
+ // process the headers using it as normal.
+ if (!IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers)) {
+ // Something went wrong, reset the headers sync.
+ peer.m_headers_sync.reset(nullptr);
+ LOCK(m_headers_presync_mutex);
+ m_headers_presync_stats.erase(peer.m_id);
+ }
+ } else {
+ LogPrint(BCLog::NET, "Ignoring low-work chain (height=%u) from peer=%d\n", chain_start_header->nHeight + headers.size(), pfrom.GetId());
}
+
+ // The peer has not yet given us a chain that meets our work threshold,
+ // so we want to prevent further processing of the headers in any case.
+ headers = {};
+ return true;
}
- {
- LOCK(cs_main);
- CNodeState *nodestate = State(pfrom.GetId());
- if (nodestate->nUnconnectingHeaders > 0) {
- LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom.GetId(), nodestate->nUnconnectingHeaders);
- }
- nodestate->nUnconnectingHeaders = 0;
+ return false;
+}
- assert(pindexLast);
- UpdateBlockAvailability(pfrom.GetId(), pindexLast->GetBlockHash());
+bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(const CBlockIndex* header)
+{
+ if (header == nullptr) {
+ return false;
+ } else if (m_chainman.m_best_header != nullptr && header == m_chainman.m_best_header->GetAncestor(header->nHeight)) {
+ return true;
+ } else if (m_chainman.ActiveChain().Contains(header)) {
+ return true;
+ }
+ return false;
+}
- // From here, pindexBestKnownBlock should be guaranteed to be non-null,
- // because it is set in UpdateBlockAvailability. Some nullptr checks
- // are still present, however, as belt-and-suspenders.
+bool PeerManagerImpl::MaybeSendGetHeaders(CNode& pfrom, const CBlockLocator& locator, Peer& peer)
+{
+ const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
- if (received_new_header && pindexLast->nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
- nodestate->m_last_block_announcement = GetTime();
- }
+ const auto current_time = NodeClock::now();
- if (nCount == MAX_HEADERS_RESULTS) {
- // Headers message had its maximum size; the peer may have more headers.
- // TODO: optimize: if pindexLast is an ancestor of m_chainman.ActiveChain().Tip or m_chainman.m_best_header, continue
- // from there instead.
- LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
- pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
- m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexLast), uint256()));
- }
-
- // If this set of headers is valid and ends in a block with at least as
- // much work as our tip, download as much as possible.
- if (CanDirectFetch() && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
- std::vector<const CBlockIndex*> vToFetch;
- const CBlockIndex *pindexWalk = pindexLast;
- // Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
- while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
- if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
- !IsBlockRequested(pindexWalk->GetBlockHash()) &&
- (!DeploymentActiveAt(*pindexWalk, m_chainman, Consensus::DEPLOYMENT_SEGWIT) || State(pfrom.GetId())->fHaveWitness)) {
- // We don't have this block, and it's not yet in flight.
- vToFetch.push_back(pindexWalk);
- }
- pindexWalk = pindexWalk->pprev;
+ // Only allow a new getheaders message to go out if we don't have a recent
+ // one already in-flight
+ if (current_time - peer.m_last_getheaders_timestamp > HEADERS_RESPONSE_TIME) {
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, locator, uint256()));
+ peer.m_last_getheaders_timestamp = current_time;
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Given a new headers tip ending in pindexLast, potentially request blocks towards that tip.
+ * We require that the given tip have at least as much work as our tip, and for
+ * our current tip to be "close to synced" (see CanDirectFetch()).
+ */
+void PeerManagerImpl::HeadersDirectFetchBlocks(CNode& pfrom, const Peer& peer, const CBlockIndex* pindexLast)
+{
+ const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
+
+ LOCK(cs_main);
+ CNodeState *nodestate = State(pfrom.GetId());
+
+ if (CanDirectFetch() && pindexLast->IsValid(BLOCK_VALID_TREE) && m_chainman.ActiveChain().Tip()->nChainWork <= pindexLast->nChainWork) {
+
+ std::vector<const CBlockIndex*> vToFetch;
+ const CBlockIndex *pindexWalk = pindexLast;
+ // Calculate all the blocks we'd need to switch to pindexLast, up to a limit.
+ while (pindexWalk && !m_chainman.ActiveChain().Contains(pindexWalk) && vToFetch.size() <= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
+ if (!(pindexWalk->nStatus & BLOCK_HAVE_DATA) &&
+ !IsBlockRequested(pindexWalk->GetBlockHash()) &&
+ (!DeploymentActiveAt(*pindexWalk, m_chainman, Consensus::DEPLOYMENT_SEGWIT) || CanServeWitnesses(peer))) {
+ // We don't have this block, and it's not yet in flight.
+ vToFetch.push_back(pindexWalk);
}
- // If pindexWalk still isn't on our main chain, we're looking at a
- // very large reorg at a time we think we're close to caught up to
- // the main chain -- this shouldn't really happen. Bail out on the
- // direct fetch and rely on parallel download instead.
- if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
- LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
- pindexLast->GetBlockHash().ToString(),
- pindexLast->nHeight);
- } else {
- std::vector<CInv> vGetData;
- // Download as much as possible, from earliest to latest.
- for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) {
- if (nodestate->nBlocksInFlight >= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
- // Can't download any more from this peer
- break;
- }
- uint32_t nFetchFlags = GetFetchFlags(pfrom);
- vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
- BlockRequested(pfrom.GetId(), *pindex);
- LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
- pindex->GetBlockHash().ToString(), pfrom.GetId());
- }
- if (vGetData.size() > 1) {
- LogPrint(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n",
- pindexLast->GetBlockHash().ToString(), pindexLast->nHeight);
+ pindexWalk = pindexWalk->pprev;
+ }
+ // If pindexWalk still isn't on our main chain, we're looking at a
+ // very large reorg at a time we think we're close to caught up to
+ // the main chain -- this shouldn't really happen. Bail out on the
+ // direct fetch and rely on parallel download instead.
+ if (!m_chainman.ActiveChain().Contains(pindexWalk)) {
+ LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n",
+ pindexLast->GetBlockHash().ToString(),
+ pindexLast->nHeight);
+ } else {
+ std::vector<CInv> vGetData;
+ // Download as much as possible, from earliest to latest.
+ for (const CBlockIndex *pindex : reverse_iterate(vToFetch)) {
+ if (nodestate->nBlocksInFlight >= MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
+ // Can't download any more from this peer
+ break;
}
- if (vGetData.size() > 0) {
- if (!m_ignore_incoming_txs &&
+ uint32_t nFetchFlags = GetFetchFlags(peer);
+ vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
+ BlockRequested(pfrom.GetId(), *pindex);
+ LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n",
+ pindex->GetBlockHash().ToString(), pfrom.GetId());
+ }
+ if (vGetData.size() > 1) {
+ LogPrint(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n",
+ pindexLast->GetBlockHash().ToString(), pindexLast->nHeight);
+ }
+ if (vGetData.size() > 0) {
+ if (!m_ignore_incoming_txs &&
nodestate->m_provides_cmpctblocks &&
vGetData.size() == 1 &&
mapBlocksInFlight.size() == 1 &&
pindexLast->pprev->IsValid(BLOCK_VALID_CHAIN)) {
- // In any case, we want to download using a compact block, not a regular one
- vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);
- }
- m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData));
+ // In any case, we want to download using a compact block, not a regular one
+ vGetData[0] = CInv(MSG_CMPCT_BLOCK, vGetData[0].hash);
}
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vGetData));
}
}
- // If we're in IBD, we want outbound peers that will serve us a useful
- // chain. Disconnect peers that are on chains with insufficient work.
- if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && nCount != MAX_HEADERS_RESULTS) {
- // When nCount < MAX_HEADERS_RESULTS, we know we have no more
- // headers to fetch from this peer.
- if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
- // This peer has too little work on their headers chain to help
- // us sync -- disconnect if it is an outbound disconnection
- // candidate.
- // Note: We compare their tip to nMinimumChainWork (rather than
- // m_chainman.ActiveChain().Tip()) because we won't start block download
- // until we have a headers chain that has at least
- // nMinimumChainWork, even if a peer has a chain past our tip,
- // as an anti-DoS measure.
- if (pfrom.IsOutboundOrBlockRelayConn()) {
- LogPrintf("Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.GetId());
- pfrom.fDisconnect = true;
- }
+ }
+}
+
+/**
+ * Given receipt of headers from a peer ending in pindexLast, along with
+ * whether that header was new and whether the headers message was full,
+ * update the state we keep for the peer.
+ */
+void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(CNode& pfrom,
+ const CBlockIndex *pindexLast, bool received_new_header, bool may_have_more_headers)
+{
+ LOCK(cs_main);
+ CNodeState *nodestate = State(pfrom.GetId());
+ if (nodestate->nUnconnectingHeaders > 0) {
+ LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom.GetId(), nodestate->nUnconnectingHeaders);
+ }
+ nodestate->nUnconnectingHeaders = 0;
+
+ assert(pindexLast);
+ UpdateBlockAvailability(pfrom.GetId(), pindexLast->GetBlockHash());
+
+ // From here, pindexBestKnownBlock should be guaranteed to be non-null,
+ // because it is set in UpdateBlockAvailability. Some nullptr checks
+ // are still present, however, as belt-and-suspenders.
+
+ if (received_new_header && pindexLast->nChainWork > m_chainman.ActiveChain().Tip()->nChainWork) {
+ nodestate->m_last_block_announcement = GetTime();
+ }
+
+ // If we're in IBD, we want outbound peers that will serve us a useful
+ // chain. Disconnect peers that are on chains with insufficient work.
+ if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && !may_have_more_headers) {
+ // If the peer has no more headers to give us, then we know we have
+ // their tip.
+ if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
+ // This peer has too little work on their headers chain to help
+ // us sync -- disconnect if it is an outbound disconnection
+ // candidate.
+ // Note: We compare their tip to nMinimumChainWork (rather than
+ // m_chainman.ActiveChain().Tip()) because we won't start block download
+ // until we have a headers chain that has at least
+ // nMinimumChainWork, even if a peer has a chain past our tip,
+ // as an anti-DoS measure.
+ if (pfrom.IsOutboundOrBlockRelayConn()) {
+ LogPrintf("Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.GetId());
+ pfrom.fDisconnect = true;
}
}
+ }
+
+ // If this is an outbound full-relay peer, check to see if we should protect
+ // it from the bad/lagging chain logic.
+ // Note that outbound block-relay peers are excluded from this protection, and
+ // thus always subject to eviction under the bad/lagging chain logic.
+ // See ChainSyncTimeoutState.
+ if (!pfrom.fDisconnect && pfrom.IsFullOutboundConn() && nodestate->pindexBestKnownBlock != nullptr) {
+ if (m_outbound_peers_with_protect_from_disconnect < MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT && nodestate->pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork && !nodestate->m_chain_sync.m_protect) {
+ LogPrint(BCLog::NET, "Protecting outbound peer=%d from eviction\n", pfrom.GetId());
+ nodestate->m_chain_sync.m_protect = true;
+ ++m_outbound_peers_with_protect_from_disconnect;
+ }
+ }
+}
- // If this is an outbound full-relay peer, check to see if we should protect
- // it from the bad/lagging chain logic.
- // Note that outbound block-relay peers are excluded from this protection, and
- // thus always subject to eviction under the bad/lagging chain logic.
- // See ChainSyncTimeoutState.
- if (!pfrom.fDisconnect && pfrom.IsFullOutboundConn() && nodestate->pindexBestKnownBlock != nullptr) {
- if (m_outbound_peers_with_protect_from_disconnect < MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT && nodestate->pindexBestKnownBlock->nChainWork >= m_chainman.ActiveChain().Tip()->nChainWork && !nodestate->m_chain_sync.m_protect) {
- LogPrint(BCLog::NET, "Protecting outbound peer=%d from eviction\n", pfrom.GetId());
- nodestate->m_chain_sync.m_protect = true;
- ++m_outbound_peers_with_protect_from_disconnect;
- }
+void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
+ std::vector<CBlockHeader>&& headers,
+ bool via_compact_block)
+{
+ size_t nCount = headers.size();
+
+ if (nCount == 0) {
+ // Nothing interesting. Stop asking this peers for more headers.
+ // If we were in the middle of headers sync, receiving an empty headers
+ // message suggests that the peer suddenly has nothing to give us
+ // (perhaps it reorged to our chain). Clear download state for this peer.
+ LOCK(peer.m_headers_sync_mutex);
+ if (peer.m_headers_sync) {
+ peer.m_headers_sync.reset(nullptr);
+ LOCK(m_headers_presync_mutex);
+ m_headers_presync_stats.erase(pfrom.GetId());
}
+ return;
+ }
+
+ // Before we do any processing, make sure these pass basic sanity checks.
+ // We'll rely on headers having valid proof-of-work further down, as an
+ // anti-DoS criteria (note: this check is required before passing any
+ // headers into HeadersSyncState).
+ if (!CheckHeadersPoW(headers, m_chainparams.GetConsensus(), peer)) {
+ // Misbehaving() calls are handled within CheckHeadersPoW(), so we can
+ // just return. (Note that even if a header is announced via compact
+ // block, the header itself should be valid, so this type of error can
+ // always be punished.)
+ return;
}
+ const CBlockIndex *pindexLast = nullptr;
+
+ // We'll set already_validated_work to true if these headers are
+ // successfully processed as part of a low-work headers sync in progress
+ // (either in PRESYNC or REDOWNLOAD phase).
+ // If true, this will mean that any headers returned to us (ie during
+ // REDOWNLOAD) can be validated without further anti-DoS checks.
+ bool already_validated_work = false;
+
+ // If we're in the middle of headers sync, let it do its magic.
+ bool have_headers_sync = false;
+ {
+ LOCK(peer.m_headers_sync_mutex);
+
+ already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
+
+ // The headers we passed in may have been:
+ // - untouched, perhaps if no headers-sync was in progress, or some
+ // failure occurred
+ // - erased, such as if the headers were successfully processed and no
+ // additional headers processing needs to take place (such as if we
+ // are still in PRESYNC)
+ // - replaced with headers that are now ready for validation, such as
+ // during the REDOWNLOAD phase of a low-work headers sync.
+ // So just check whether we still have headers that we need to process,
+ // or not.
+ if (headers.empty()) {
+ return;
+ }
+
+ have_headers_sync = !!peer.m_headers_sync;
+ }
+
+ // Do these headers connect to something in our block index?
+ const CBlockIndex *chain_start_header{WITH_LOCK(::cs_main, return m_chainman.m_blockman.LookupBlockIndex(headers[0].hashPrevBlock))};
+ bool headers_connect_blockindex{chain_start_header != nullptr};
+
+ if (!headers_connect_blockindex) {
+ if (nCount <= MAX_BLOCKS_TO_ANNOUNCE) {
+ // If this looks like it could be a BIP 130 block announcement, use
+ // special logic for handling headers that don't connect, as this
+ // could be benign.
+ HandleFewUnconnectingHeaders(pfrom, peer, headers);
+ } else {
+ Misbehaving(peer, 10, "invalid header received");
+ }
+ return;
+ }
+
+ // If the headers we received are already in memory and an ancestor of
+ // m_best_header or our tip, skip anti-DoS checks. These headers will not
+ // use any more memory (and we are not leaking information that could be
+ // used to fingerprint us).
+ const CBlockIndex *last_received_header{nullptr};
+ {
+ LOCK(cs_main);
+ last_received_header = m_chainman.m_blockman.LookupBlockIndex(headers.back().GetHash());
+ if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
+ already_validated_work = true;
+ }
+ }
+
+ // If our peer has NetPermissionFlags::NoBan privileges, then bypass our
+ // anti-DoS logic (this saves bandwidth when we connect to a trusted peer
+ // on startup).
+ if (pfrom.HasPermission(NetPermissionFlags::NoBan)) {
+ already_validated_work = true;
+ }
+
+ // At this point, the headers connect to something in our block index.
+ // Do anti-DoS checks to determine if we should process or store for later
+ // processing.
+ if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
+ chain_start_header, headers)) {
+ // If we successfully started a low-work headers sync, then there
+ // should be no headers to process any further.
+ Assume(headers.empty());
+ return;
+ }
+
+ // At this point, we have a set of headers with sufficient work on them
+ // which can be processed.
+
+ // If we don't have the last header, then this peer will have given us
+ // something new (if these headers are valid).
+ bool received_new_header{last_received_header == nullptr};
+
+ // Now process all the headers.
+ BlockValidationState state;
+ if (!m_chainman.ProcessNewBlockHeaders(headers, /*min_pow_checked=*/true, state, &pindexLast)) {
+ if (state.IsInvalid()) {
+ MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
+ return;
+ }
+ }
+ Assume(pindexLast);
+
+ // Consider fetching more headers if we are not using our headers-sync mechanism.
+ if (nCount == MAX_HEADERS_RESULTS && !have_headers_sync) {
+ // Headers message had its maximum size; the peer may have more headers.
+ if (MaybeSendGetHeaders(pfrom, GetLocator(pindexLast), peer)) {
+ LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n",
+ pindexLast->nHeight, pfrom.GetId(), peer.m_starting_height);
+ }
+ }
+
+ UpdatePeerStateForReceivedHeaders(pfrom, pindexLast, received_new_header, nCount == MAX_HEADERS_RESULTS);
+
+ // Consider immediately downloading blocks.
+ HeadersDirectFetchBlocks(pfrom, peer, pindexLast);
+
return;
}
@@ -2458,7 +2966,7 @@ void PeerManagerImpl::ProcessOrphanTx(std::set<uint256>& orphan_work_set)
}
}
-bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer,
+bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& node, Peer& peer,
BlockFilterType filter_type, uint32_t start_height,
const uint256& stop_hash, uint32_t max_height_diff,
const CBlockIndex*& stop_index,
@@ -2466,11 +2974,11 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer,
{
const bool supported_filter_type =
(filter_type == BlockFilterType::BASIC &&
- (peer.GetLocalServices() & NODE_COMPACT_FILTERS));
+ (peer.m_our_services & NODE_COMPACT_FILTERS));
if (!supported_filter_type) {
LogPrint(BCLog::NET, "peer %d requested unsupported block filter type: %d\n",
- peer.GetId(), static_cast<uint8_t>(filter_type));
- peer.fDisconnect = true;
+ node.GetId(), static_cast<uint8_t>(filter_type));
+ node.fDisconnect = true;
return false;
}
@@ -2481,8 +2989,8 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer,
// Check that the stop block exists and the peer would be allowed to fetch it.
if (!stop_index || !BlockRequestAllowed(stop_index)) {
LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n",
- peer.GetId(), stop_hash.ToString());
- peer.fDisconnect = true;
+ node.GetId(), stop_hash.ToString());
+ node.fDisconnect = true;
return false;
}
}
@@ -2491,14 +2999,14 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer,
if (start_height > stop_height) {
LogPrint(BCLog::NET, "peer %d sent invalid getcfilters/getcfheaders with " /* Continued */
"start height %d and stop height %d\n",
- peer.GetId(), start_height, stop_height);
- peer.fDisconnect = true;
+ node.GetId(), start_height, stop_height);
+ node.fDisconnect = true;
return false;
}
if (stop_height - start_height >= max_height_diff) {
LogPrint(BCLog::NET, "peer %d requested too many cfilters/cfheaders: %d / %d\n",
- peer.GetId(), stop_height - start_height + 1, max_height_diff);
- peer.fDisconnect = true;
+ node.GetId(), stop_height - start_height + 1, max_height_diff);
+ node.fDisconnect = true;
return false;
}
@@ -2511,7 +3019,7 @@ bool PeerManagerImpl::PrepareBlockFilterRequest(CNode& peer,
return true;
}
-void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv)
+void PeerManagerImpl::ProcessGetCFilters(CNode& node,Peer& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint32_t start_height;
@@ -2523,7 +3031,7 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv)
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
+ if (!PrepareBlockFilterRequest(node, peer, filter_type, start_height, stop_hash,
MAX_GETCFILTERS_SIZE, stop_index, filter_index)) {
return;
}
@@ -2536,13 +3044,13 @@ void PeerManagerImpl::ProcessGetCFilters(CNode& peer, CDataStream& vRecv)
}
for (const auto& filter : filters) {
- CSerializedNetMsg msg = CNetMsgMaker(peer.GetCommonVersion())
+ CSerializedNetMsg msg = CNetMsgMaker(node.GetCommonVersion())
.Make(NetMsgType::CFILTER, filter);
- m_connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&node, std::move(msg));
}
}
-void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv)
+void PeerManagerImpl::ProcessGetCFHeaders(CNode& node, Peer& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint32_t start_height;
@@ -2554,7 +3062,7 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv)
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, filter_type, start_height, stop_hash,
+ if (!PrepareBlockFilterRequest(node, peer, filter_type, start_height, stop_hash,
MAX_GETCFHEADERS_SIZE, stop_index, filter_index)) {
return;
}
@@ -2577,16 +3085,16 @@ void PeerManagerImpl::ProcessGetCFHeaders(CNode& peer, CDataStream& vRecv)
return;
}
- CSerializedNetMsg msg = CNetMsgMaker(peer.GetCommonVersion())
+ CSerializedNetMsg msg = CNetMsgMaker(node.GetCommonVersion())
.Make(NetMsgType::CFHEADERS,
filter_type_ser,
stop_index->GetBlockHash(),
prev_header,
filter_hashes);
- m_connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&node, std::move(msg));
}
-void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv)
+void PeerManagerImpl::ProcessGetCFCheckPt(CNode& node, Peer& peer, CDataStream& vRecv)
{
uint8_t filter_type_ser;
uint256 stop_hash;
@@ -2597,7 +3105,7 @@ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv)
const CBlockIndex* stop_index;
BlockFilterIndex* filter_index;
- if (!PrepareBlockFilterRequest(peer, filter_type, /*start_height=*/0, stop_hash,
+ if (!PrepareBlockFilterRequest(node, peer, filter_type, /*start_height=*/0, stop_hash,
/*max_height_diff=*/std::numeric_limits<uint32_t>::max(),
stop_index, filter_index)) {
return;
@@ -2618,18 +3126,18 @@ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv)
}
}
- CSerializedNetMsg msg = CNetMsgMaker(peer.GetCommonVersion())
+ CSerializedNetMsg msg = CNetMsgMaker(node.GetCommonVersion())
.Make(NetMsgType::CFCHECKPT,
filter_type_ser,
stop_index->GetBlockHash(),
headers);
- m_connman.PushMessage(&peer, std::move(msg));
+ m_connman.PushMessage(&node, std::move(msg));
}
-void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing)
+void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing, bool min_pow_checked)
{
bool new_block{false};
- m_chainman.ProcessNewBlock(block, force_processing, &new_block);
+ m_chainman.ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
if (new_block) {
node.m_last_block_time = GetTime<std::chrono::seconds>();
} else {
@@ -2745,7 +3253,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
- pfrom.nServices = nServices;
+ pfrom.m_has_all_wanted_services = HasAllDesirableServiceFlags(nServices);
+ peer->m_their_services = nServices;
pfrom.SetAddrLocal(addrMe);
{
LOCK(pfrom.m_subver_mutex);
@@ -2753,18 +3262,12 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
peer->m_starting_height = starting_height;
- // set nodes not relaying blocks and tx and not serving (parts) of the historical blockchain as "clients"
- pfrom.fClient = (!(nServices & NODE_NETWORK) && !(nServices & NODE_NETWORK_LIMITED));
-
- // set nodes not capable of serving the complete blockchain history as "limited nodes"
- pfrom.m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED));
-
// We only initialize the m_tx_relay data structure if:
// - this isn't an outbound block-relay-only connection; and
// - fRelay=true or we're offering NODE_BLOOM to this peer
// (NODE_BLOOM means that the peer may turn on tx relay later)
if (!pfrom.IsBlockOnlyConn() &&
- (fRelay || (pfrom.GetLocalServices() & NODE_BLOOM))) {
+ (fRelay || (peer->m_our_services & NODE_BLOOM))) {
auto* const tx_relay = peer->SetTxRelay();
{
LOCK(tx_relay->m_bloom_filter_mutex);
@@ -2773,17 +3276,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (fRelay) pfrom.m_relays_txs = true;
}
- if((nServices & NODE_WITNESS))
- {
- LOCK(cs_main);
- State(pfrom.GetId())->fHaveWitness = true;
- }
-
// Potentially mark this peer as a preferred download peer.
{
LOCK(cs_main);
CNodeState* state = State(pfrom.GetId());
- state->fPreferredDownload = (!pfrom.IsInboundConn() || pfrom.HasPermission(NetPermissionFlags::NoBan)) && !pfrom.IsAddrFetchConn() && !pfrom.fClient;
+ state->fPreferredDownload = (!pfrom.IsInboundConn() || pfrom.HasPermission(NetPermissionFlags::NoBan)) && !pfrom.IsAddrFetchConn() && CanServeBlocks(*peer);
m_num_preferred_download_peers += state->fPreferredDownload;
}
@@ -2802,7 +3299,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// indicate to the peer that we will participate in addr relay.
if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
{
- CAddress addr = GetLocalAddress(&pfrom.addr, pfrom.GetLocalServices());
+ CAddress addr{GetLocalAddress(pfrom.addr), peer->m_our_services, Now<NodeSeconds>()};
FastRandomContext insecure_rand;
if (addr.IsRoutable())
{
@@ -2898,13 +3395,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
pfrom.ConnectionTypeAsString());
}
- if (pfrom.GetCommonVersion() >= SENDHEADERS_VERSION) {
- // Tell our peer we prefer to receive headers rather than inv's
- // We send this to non-NODE NETWORK peers as well, because even
- // non-NODE NETWORK peers can announce blocks (such as pruning
- // nodes)
- m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDHEADERS));
- }
if (pfrom.GetCommonVersion() >= SHORT_IDS_BLOCKS_VERSION) {
// Tell our peer we are willing to provide version 2 cmpctblocks.
// However, we do not request new block announcements using
@@ -2913,6 +3403,21 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// they may wish to request compact blocks from us
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, /*high_bandwidth=*/false, /*version=*/CMPCTBLOCKS_VERSION));
}
+
+ if (auto tx_relay = peer->GetTxRelay()) {
+ // `TxRelay::m_tx_inventory_to_send` must be empty before the
+ // version handshake is completed as
+ // `TxRelay::m_next_inv_send_time` is first initialised in
+ // `SendMessages` after the verack is received. Any transactions
+ // received during the version handshake would otherwise
+ // immediately be advertised without random delay, potentially
+ // leaking the time of arrival to a spy.
+ Assume(WITH_LOCK(
+ tx_relay->m_tx_inventory_mutex,
+ return tx_relay->m_tx_inventory_to_send.empty() &&
+ tx_relay->m_next_inv_send_time == 0s));
+ }
+
pfrom.fSuccessfullyConnected = true;
return;
}
@@ -3001,21 +3506,20 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (vAddr.size() > MAX_ADDR_TO_SEND)
{
- Misbehaving(pfrom.GetId(), 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
+ Misbehaving(*peer, 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
return;
}
// Store the new addresses
std::vector<CAddress> vAddrOk;
- int64_t nNow = GetAdjustedTime();
- int64_t nSince = nNow - 10 * 60;
+ const auto current_a_time{Now<NodeSeconds>()};
// Update/increment addr rate limiting bucket.
const auto current_time{GetTime<std::chrono::microseconds>()};
if (peer->m_addr_token_bucket < MAX_ADDR_PROCESSING_TOKEN_BUCKET) {
// Don't increment bucket if it's already full
const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
- const double increment = CountSecondsDouble(time_diff) * MAX_ADDR_RATE_PER_SECOND;
+ const double increment = Ticks<SecondsDouble>(time_diff) * MAX_ADDR_RATE_PER_SECOND;
peer->m_addr_token_bucket = std::min<double>(peer->m_addr_token_bucket + increment, MAX_ADDR_PROCESSING_TOKEN_BUCKET);
}
peer->m_addr_token_timestamp = current_time;
@@ -3044,8 +3548,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (!MayHaveUsefulAddressDB(addr.nServices) && !HasAllDesirableServiceFlags(addr.nServices))
continue;
- if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
- addr.nTime = nNow - 5 * 24 * 60 * 60;
+ if (addr.nTime <= NodeSeconds{100000000s} || addr.nTime > current_a_time + 10min) {
+ addr.nTime = current_a_time - 5 * 24h;
+ }
AddAddressKnown(*peer, addr);
if (m_banman && (m_banman->IsDiscouraged(addr) || m_banman->IsBanned(addr))) {
// Do not process banned/discouraged addresses beyond remembering we received them
@@ -3053,7 +3558,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
++num_proc;
bool fReachable = IsReachable(addr);
- if (addr.nTime > nSince && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
+ if (addr.nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.IsRoutable()) {
// Relay to a limited number of other nodes
RelayAddress(pfrom.GetId(), addr, fReachable);
}
@@ -3066,7 +3571,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
LogPrint(BCLog::NET, "Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
vAddr.size(), num_proc, num_rate_limit, pfrom.GetId());
- m_addrman.Add(vAddrOk, pfrom.addr, 2 * 60 * 60);
+ m_addrman.Add(vAddrOk, pfrom.addr, 2h);
if (vAddr.size() < 1000) peer->m_getaddr_sent = false;
// AddrFetch: Require multiple addresses to avoid disconnecting on self-announcements
@@ -3082,7 +3587,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ)
{
- Misbehaving(pfrom.GetId(), 20, strprintf("inv message size = %u", vInv.size()));
+ Misbehaving(*peer, 20, strprintf("inv message size = %u", vInv.size()));
return;
}
@@ -3112,8 +3617,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
UpdateBlockAvailability(pfrom.GetId(), inv.hash);
if (!fAlreadyHave && !fImporting && !fReindex && !IsBlockRequested(inv.hash)) {
// Headers-first is the primary method of announcement on
- // the network. If a node fell back to sending blocks by inv,
- // it's probably for a re-org. The final block hash
+ // the network. If a node fell back to sending blocks by
+ // inv, it may be for a re-org, or because we haven't
+ // completed initial headers sync. The final block hash
// provided should be the highest, so send a getheaders and
// then fetch the blocks we need to catch up.
best_block = &inv.hash;
@@ -3138,8 +3644,31 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
if (best_block != nullptr) {
- m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), *best_block));
- LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", m_chainman.m_best_header->nHeight, best_block->ToString(), pfrom.GetId());
+ // If we haven't started initial headers-sync with this peer, then
+ // consider sending a getheaders now. On initial startup, there's a
+ // reliability vs bandwidth tradeoff, where we are only trying to do
+ // initial headers sync with one peer at a time, with a long
+ // timeout (at which point, if the sync hasn't completed, we will
+ // disconnect the peer and then choose another). In the meantime,
+ // as new blocks are found, we are willing to add one new peer per
+ // block to sync with as well, to sync quicker in the case where
+ // our initial peer is unresponsive (but less bandwidth than we'd
+ // use if we turned on sync with all peers).
+ CNodeState& state{*Assert(State(pfrom.GetId()))};
+ if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
+ if (MaybeSendGetHeaders(pfrom, GetLocator(m_chainman.m_best_header), *peer)) {
+ LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n",
+ m_chainman.m_best_header->nHeight, best_block->ToString(),
+ pfrom.GetId());
+ }
+ if (!state.fSyncStarted) {
+ peer->m_inv_triggered_getheaders_before_sync = true;
+ // Update the last block hash that triggered a new headers
+ // sync, so that we don't turn on headers sync with more
+ // than 1 new peer every new block.
+ m_last_block_inv_triggering_headers_sync = *best_block;
+ }
+ }
}
return;
@@ -3150,7 +3679,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ)
{
- Misbehaving(pfrom.GetId(), 20, strprintf("getdata message size = %u", vInv.size()));
+ Misbehaving(*peer, 20, strprintf("getdata message size = %u", vInv.size()));
return;
}
@@ -3248,7 +3777,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// Unlock m_most_recent_block_mutex to avoid cs_main lock inversion
}
if (recent_block) {
- SendBlockTransactions(pfrom, *recent_block, req);
+ SendBlockTransactions(pfrom, *peer, *recent_block, req);
return;
}
@@ -3266,7 +3795,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus());
assert(ret);
- SendBlockTransactions(pfrom, block, req);
+ SendBlockTransactions(pfrom, *peer, block, req);
return;
}
}
@@ -3312,7 +3841,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// others.
if (m_chainman.ActiveTip() == nullptr ||
(m_chainman.ActiveTip()->nChainWork < nMinimumChainWork && !pfrom.HasPermission(NetPermissionFlags::Download))) {
- LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because active chain has too little work\n", pfrom.GetId());
+ LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.GetId());
+ // Just respond with an empty headers message, to tell the peer to
+ // go away but not treat us as unresponsive.
+ m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::HEADERS, std::vector<CBlock>()));
return;
}
@@ -3497,10 +4029,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// DoS prevention: do not allow m_orphanage to grow unbounded (see CVE-2012-3789)
unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, gArgs.GetIntArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
- unsigned int nEvicted = m_orphanage.LimitOrphans(nMaxOrphanTx);
- if (nEvicted > 0) {
- LogPrint(BCLog::MEMPOOL, "orphanage overflow, removed %u tx\n", nEvicted);
- }
+ m_orphanage.LimitOrphans(nMaxOrphanTx);
} else {
LogPrint(BCLog::MEMPOOL, "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString());
// We will continue to reject this tx since it has rejected
@@ -3591,10 +4120,16 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
{
LOCK(cs_main);
- if (!m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
+ const CBlockIndex* prev_block = m_chainman.m_blockman.LookupBlockIndex(cmpctblock.header.hashPrevBlock);
+ if (!prev_block) {
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
- if (!m_chainman.ActiveChainstate().IsInitialBlockDownload())
- m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(m_chainman.m_best_header), uint256()));
+ if (!m_chainman.ActiveChainstate().IsInitialBlockDownload()) {
+ MaybeSendGetHeaders(pfrom, GetLocator(m_chainman.m_best_header), *peer);
+ }
+ return;
+ } else if (prev_block->nChainWork + CalculateHeadersWork({cmpctblock.header}) < GetAntiDoSWorkThreshold()) {
+ // If we get a low-work header in a compact block, we can ignore it.
+ LogPrint(BCLog::NET, "Ignoring low-work compact block from peer %d\n", pfrom.GetId());
return;
}
@@ -3605,7 +4140,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
const CBlockIndex *pindex = nullptr;
BlockValidationState state;
- if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, &pindex)) {
+ if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, /*min_pow_checked=*/true, state, &pindex)) {
if (state.IsInvalid()) {
MaybePunishNodeForBlock(pfrom.GetId(), state, /*via_compact_block=*/true, "invalid header via cmpctblock");
return;
@@ -3654,7 +4189,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// We requested this block for some reason, but our mempool will probably be useless
// so we just grab the block via normal getdata
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(*peer), cmpctblock.header.GetHash());
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
}
return;
@@ -3685,12 +4220,12 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
ReadStatus status = partialBlock.InitData(cmpctblock, vExtraTxnForCompact);
if (status == READ_STATUS_INVALID) {
RemoveBlockRequest(pindex->GetBlockHash()); // Reset in-flight state in case Misbehaving does not result in a disconnect
- Misbehaving(pfrom.GetId(), 100, "invalid compact block");
+ Misbehaving(*peer, 100, "invalid compact block");
return;
} else if (status == READ_STATUS_FAILED) {
// Duplicate txindexes, the block is now in-flight, so just request it
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(*peer), cmpctblock.header.GetHash());
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
return;
}
@@ -3733,7 +4268,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// We requested this block, but its far into the future, so our
// mempool will probably be useless - request the block normally
std::vector<CInv> vInv(1);
- vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(pfrom), cmpctblock.header.GetHash());
+ vInv[0] = CInv(MSG_BLOCK | GetFetchFlags(*peer), cmpctblock.header.GetHash());
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, vInv));
return;
} else {
@@ -3772,7 +4307,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// we have a chain with at least nMinimumChainWork), and we ignore
// compact blocks with less work than our tip, it is safe to treat
// reconstructed compact blocks as having been requested.
- ProcessBlock(pfrom, pblock, /*force_processing=*/true);
+ ProcessBlock(pfrom, pblock, /*force_processing=*/true, /*min_pow_checked=*/true);
LOCK(cs_main); // hold cs_main for CBlockIndex::IsValid()
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS)) {
// Clear download state for this block, which is in
@@ -3812,12 +4347,12 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
if (status == READ_STATUS_INVALID) {
RemoveBlockRequest(resp.blockhash); // Reset in-flight state in case Misbehaving does not result in a disconnect
- Misbehaving(pfrom.GetId(), 100, "invalid compact block/non-matching block transactions");
+ Misbehaving(*peer, 100, "invalid compact block/non-matching block transactions");
return;
} else if (status == READ_STATUS_FAILED) {
// Might have collided, fall back to getdata now :(
std::vector<CInv> invs;
- invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(pfrom), resp.blockhash));
+ invs.push_back(CInv(MSG_BLOCK | GetFetchFlags(*peer), resp.blockhash));
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::GETDATA, invs));
} else {
// Block is either okay, or possibly we received
@@ -3855,7 +4390,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// disk-space attacks), but this should be safe due to the
// protections in the compact block handler -- see related comment
// in compact block optimistic reconstruction handling.
- ProcessBlock(pfrom, pblock, /*force_processing=*/true);
+ ProcessBlock(pfrom, pblock, /*force_processing=*/true, /*min_pow_checked=*/true);
}
return;
}
@@ -3868,12 +4403,16 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
}
+ // Assume that this is in response to any outstanding getheaders
+ // request we may have sent, and clear out the time of our last request
+ peer->m_last_getheaders_timestamp = {};
+
std::vector<CBlockHeader> headers;
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
unsigned int nCount = ReadCompactSize(vRecv);
if (nCount > MAX_HEADERS_RESULTS) {
- Misbehaving(pfrom.GetId(), 20, strprintf("headers message size = %u", nCount));
+ Misbehaving(*peer, 20, strprintf("headers message size = %u", nCount));
return;
}
headers.resize(nCount);
@@ -3882,7 +4421,23 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
}
- return ProcessHeadersMessage(pfrom, *peer, headers, /*via_compact_block=*/false);
+ ProcessHeadersMessage(pfrom, *peer, std::move(headers), /*via_compact_block=*/false);
+
+ // Check if the headers presync progress needs to be reported to validation.
+ // This needs to be done without holding the m_headers_presync_mutex lock.
+ if (m_headers_presync_should_signal.exchange(false)) {
+ HeadersPresyncStats stats;
+ {
+ LOCK(m_headers_presync_mutex);
+ auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
+ if (it != m_headers_presync_stats.end()) stats = it->second;
+ }
+ if (stats.second) {
+ m_chainman.ReportHeadersPresync(stats.first, stats.second->first, stats.second->second);
+ }
+ }
+
+ return;
}
if (msg_type == NetMsgType::BLOCK)
@@ -3900,6 +4455,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
bool forceProcessing = false;
const uint256 hash(pblock->GetHash());
+ bool min_pow_checked = false;
{
LOCK(cs_main);
// Always process the block if we requested it, since we may
@@ -3910,8 +4466,14 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// which peers send us compact blocks, so the race between here and
// cs_main in ProcessNewBlock is fine.
mapBlockSource.emplace(hash, std::make_pair(pfrom.GetId(), true));
+
+ // Check work on this block against our anti-dos thresholds.
+ const CBlockIndex* prev_block = m_chainman.m_blockman.LookupBlockIndex(pblock->hashPrevBlock);
+ if (prev_block && prev_block->nChainWork + CalculateHeadersWork({pblock->GetBlockHeader()}) >= GetAntiDoSWorkThreshold()) {
+ min_pow_checked = true;
+ }
}
- ProcessBlock(pfrom, pblock, forceProcessing);
+ ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
return;
}
@@ -3953,7 +4515,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
if (msg_type == NetMsgType::MEMPOOL) {
- if (!(pfrom.GetLocalServices() & NODE_BLOOM) && !pfrom.HasPermission(NetPermissionFlags::Mempool))
+ if (!(peer->m_our_services & NODE_BLOOM) && !pfrom.HasPermission(NetPermissionFlags::Mempool))
{
if (!pfrom.HasPermission(NetPermissionFlags::NoBan))
{
@@ -4056,7 +4618,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
if (msg_type == NetMsgType::FILTERLOAD) {
- if (!(pfrom.GetLocalServices() & NODE_BLOOM)) {
+ if (!(peer->m_our_services & NODE_BLOOM)) {
LogPrint(BCLog::NET, "filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.GetId());
pfrom.fDisconnect = true;
return;
@@ -4067,7 +4629,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (!filter.IsWithinSizeConstraints())
{
// There is no excuse for sending a too-large filter
- Misbehaving(pfrom.GetId(), 100, "too-large bloom filter");
+ Misbehaving(*peer, 100, "too-large bloom filter");
} else if (auto tx_relay = peer->GetTxRelay(); tx_relay != nullptr) {
{
LOCK(tx_relay->m_bloom_filter_mutex);
@@ -4075,12 +4637,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
tx_relay->m_relay_txs = true;
}
pfrom.m_bloom_filter_loaded = true;
+ pfrom.m_relays_txs = true;
}
return;
}
if (msg_type == NetMsgType::FILTERADD) {
- if (!(pfrom.GetLocalServices() & NODE_BLOOM)) {
+ if (!(peer->m_our_services & NODE_BLOOM)) {
LogPrint(BCLog::NET, "filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.GetId());
pfrom.fDisconnect = true;
return;
@@ -4102,13 +4665,13 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
}
if (bad) {
- Misbehaving(pfrom.GetId(), 100, "bad filteradd message");
+ Misbehaving(*peer, 100, "bad filteradd message");
}
return;
}
if (msg_type == NetMsgType::FILTERCLEAR) {
- if (!(pfrom.GetLocalServices() & NODE_BLOOM)) {
+ if (!(peer->m_our_services & NODE_BLOOM)) {
LogPrint(BCLog::NET, "filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.GetId());
pfrom.fDisconnect = true;
return;
@@ -4139,17 +4702,17 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
if (msg_type == NetMsgType::GETCFILTERS) {
- ProcessGetCFilters(pfrom, vRecv);
+ ProcessGetCFilters(pfrom, *peer, vRecv);
return;
}
if (msg_type == NetMsgType::GETCFHEADERS) {
- ProcessGetCFHeaders(pfrom, vRecv);
+ ProcessGetCFHeaders(pfrom, *peer, vRecv);
return;
}
if (msg_type == NetMsgType::GETCFCHECKPT) {
- ProcessGetCFCheckPt(pfrom, vRecv);
+ ProcessGetCFCheckPt(pfrom, *peer, vRecv);
return;
}
@@ -4295,7 +4858,7 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
return fMoreWork;
}
-void PeerManagerImpl::ConsiderEviction(CNode& pto, std::chrono::seconds time_in_seconds)
+void PeerManagerImpl::ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
{
AssertLockHeld(cs_main);
@@ -4333,10 +4896,15 @@ void PeerManagerImpl::ConsiderEviction(CNode& pto, std::chrono::seconds time_in_
pto.fDisconnect = true;
} else {
assert(state.m_chain_sync.m_work_header);
+ // Here, we assume that the getheaders message goes out,
+ // because it'll either go out or be skipped because of a
+ // getheaders in-flight already, in which case the peer should
+ // still respond to us with a sufficiently high work chain tip.
+ MaybeSendGetHeaders(pto,
+ GetLocator(state.m_chain_sync.m_work_header->pprev),
+ peer);
LogPrint(BCLog::NET, "sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto.GetId(), state.pindexBestKnownBlock != nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() : "<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString());
- m_connman.PushMessage(&pto, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(state.m_chain_sync.m_work_header->pprev), uint256()));
state.m_chain_sync.m_sent_getheaders = true;
- constexpr auto HEADERS_RESPONSE_TIME{2min};
// Bump the timeout to allow a response, which could clear the timeout
// (if the response shows the peer has synced), reset the timeout (if
// the peer syncs to the required work but not to our tip), or result
@@ -4540,9 +5108,10 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
if (peer.m_next_local_addr_send != 0us) {
peer.m_addr_known->reset();
}
- if (std::optional<CAddress> local_addr = GetLocalAddrForPeer(&node)) {
+ 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, insecure_rand);
}
peer.m_next_local_addr_send = GetExponentialRand(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
@@ -4589,6 +5158,27 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
}
}
+void PeerManagerImpl::MaybeSendSendHeaders(CNode& node, Peer& peer)
+{
+ // Delay sending SENDHEADERS (BIP 130) until we're done with an
+ // initial-headers-sync with this peer. Receiving headers announcements for
+ // new blocks while trying to sync their headers chain is problematic,
+ // because of the state tracking done.
+ if (!peer.m_sent_sendheaders && node.GetCommonVersion() >= SENDHEADERS_VERSION) {
+ LOCK(cs_main);
+ CNodeState &state = *State(node.GetId());
+ if (state.pindexBestKnownBlock != nullptr &&
+ state.pindexBestKnownBlock->nChainWork > nMinimumChainWork) {
+ // Tell our peer we prefer to receive headers rather than inv's
+ // We send this to non-NODE NETWORK peers as well, because even
+ // non-NODE NETWORK peers can announce blocks (such as pruning
+ // nodes)
+ m_connman.PushMessage(&node, CNetMsgMaker(node.GetCommonVersion()).Make(NetMsgType::SENDHEADERS));
+ peer.m_sent_sendheaders = true;
+ }
+ }
+}
+
void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::microseconds current_time)
{
if (m_ignore_incoming_txs) return;
@@ -4599,7 +5189,7 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi
// transactions to us, regardless of feefilter state.
if (pto.IsBlockOnlyConn()) return;
- CAmount currentFilter = m_mempool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
+ CAmount currentFilter = m_mempool.GetMinFee().GetFeePerK();
static FeeFilterRounder g_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE}};
if (m_chainman.ActiveChainstate().IsInitialBlockDownload()) {
@@ -4616,8 +5206,8 @@ void PeerManagerImpl::MaybeSendFeefilter(CNode& pto, Peer& peer, std::chrono::mi
}
if (current_time > peer.m_next_send_feefilter) {
CAmount filterToSend = g_filter_rounder.round(currentFilter);
- // We always have a fee filter of at least minRelayTxFee
- filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
+ // We always have a fee filter of at least the min relay fee
+ filterToSend = std::max(filterToSend, m_mempool.m_min_relay_feerate.GetFeePerK());
if (filterToSend != peer.m_fee_filter_sent) {
m_connman.PushMessage(&pto, CNetMsgMaker(pto.GetCommonVersion()).Make(NetMsgType::FEEFILTER, filterToSend));
peer.m_fee_filter_sent = filterToSend;
@@ -4710,6 +5300,8 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
MaybeSendAddr(*pto, *peer, current_time);
+ MaybeSendSendHeaders(*pto, *peer);
+
{
LOCK(cs_main);
@@ -4726,7 +5318,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
bool sync_blocks_and_headers_from_peer = false;
if (state.fPreferredDownload) {
sync_blocks_and_headers_from_peer = true;
- } else if (!pto->fClient && !pto->IsAddrFetchConn()) {
+ } else if (CanServeBlocks(*peer) && !pto->IsAddrFetchConn()) {
// Typically this is an inbound peer. If we don't have any outbound
// peers, or if we aren't downloading any blocks from such peers,
// then allow block downloads from this peer, too.
@@ -4741,18 +5333,9 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
}
}
- if (!state.fSyncStarted && !pto->fClient && !fImporting && !fReindex) {
+ if (!state.fSyncStarted && CanServeBlocks(*peer) && !fImporting && !fReindex) {
// Only actively request headers from a single peer, unless we're close to today.
- if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
- state.fSyncStarted = true;
- state.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE +
- (
- // Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling
- // to maintain precision
- std::chrono::microseconds{HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER} *
- (GetAdjustedTime() - m_chainman.m_best_header->GetBlockTime()) / consensusParams.nPowTargetSpacing
- );
- nSyncStarted++;
+ if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() > GetAdjustedTime() - 24h) {
const CBlockIndex* pindexStart = m_chainman.m_best_header;
/* If possible, start at the block preceding the currently
best known header. This ensures that we always get a
@@ -4763,8 +5346,19 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
got back an empty response. */
if (pindexStart->pprev)
pindexStart = pindexStart->pprev;
- LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), peer->m_starting_height);
- m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, m_chainman.ActiveChain().GetLocator(pindexStart), uint256()));
+ if (MaybeSendGetHeaders(*pto, GetLocator(pindexStart), *peer)) {
+ LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), peer->m_starting_height);
+
+ state.fSyncStarted = true;
+ state.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE +
+ (
+ // Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling
+ // to maintain precision
+ std::chrono::microseconds{HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER} *
+ Ticks<std::chrono::seconds>(GetAdjustedTime() - m_chainman.m_best_header->Time()) / consensusParams.nPowTargetSpacing
+ );
+ nSyncStarted++;
+ }
}
}
@@ -4772,7 +5366,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Try sending block announcements via headers
//
{
- // If we have less than MAX_BLOCKS_TO_ANNOUNCE in our
+ // If we have no more than MAX_BLOCKS_TO_ANNOUNCE in our
// list of block hashes we're relaying, and our peer wants
// headers announcements, then find the first header
// not yet known to our peer but would connect, and send.
@@ -5078,7 +5672,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Check for headers sync timeouts
if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) {
// Detect whether this is a stalling initial-headers-sync peer
- if (m_chainman.m_best_header->GetBlockTime() <= GetAdjustedTime() - 24 * 60 * 60) {
+ if (m_chainman.m_best_header->Time() <= GetAdjustedTime() - 24h) {
if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
// Disconnect a peer (without NetPermissionFlags::NoBan permission) if it is our only sync peer,
// and we have others we could be using instead.
@@ -5110,18 +5704,18 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// Check that outbound peers have reasonable chains
// GetTime() is used by this anti-DoS logic so we can test this using mocktime
- ConsiderEviction(*pto, GetTime<std::chrono::seconds>());
+ ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
//
// Message: getdata (blocks)
//
std::vector<CInv> vGetData;
- if (!pto->fClient && ((sync_blocks_and_headers_from_peer && !pto->m_limited_node) || !m_chainman.ActiveChainstate().IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
+ if (CanServeBlocks(*peer) && ((sync_blocks_and_headers_from_peer && !IsLimitedPeer(*peer)) || !m_chainman.ActiveChainstate().IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
std::vector<const CBlockIndex*> vToDownload;
NodeId staller = -1;
- FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
+ FindNextBlocksToDownload(*peer, MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
for (const CBlockIndex *pindex : vToDownload) {
- uint32_t nFetchFlags = GetFetchFlags(*pto);
+ uint32_t nFetchFlags = GetFetchFlags(*peer);
vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash()));
BlockRequested(pto->GetId(), *pindex);
LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
@@ -5148,7 +5742,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
if (!AlreadyHaveTx(gtxid)) {
LogPrint(BCLog::NET, "Requesting %s %s peer=%d\n", gtxid.IsWtxid() ? "wtx" : "tx",
gtxid.GetHash().ToString(), pto->GetId());
- vGetData.emplace_back(gtxid.IsWtxid() ? MSG_WTX : (MSG_TX | GetFetchFlags(*pto)), gtxid.GetHash());
+ vGetData.emplace_back(gtxid.IsWtxid() ? MSG_WTX : (MSG_TX | GetFetchFlags(*peer)), gtxid.GetHash());
if (vGetData.size() >= MAX_GETDATA_SZ) {
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData));
vGetData.clear();
diff --git a/src/net_processing.h b/src/net_processing.h
index d5c73e6c79..0a882b1e53 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -34,6 +34,8 @@ struct CNodeStateStats {
uint64_t m_addr_processed = 0;
uint64_t m_addr_rate_limited = 0;
bool m_addr_relay_enabled{false};
+ ServiceFlags their_services;
+ int64_t presync_height{-1};
};
class PeerManager : public CValidationInterface, public NetEventsInterface
@@ -71,12 +73,8 @@ public:
/** Set the best height */
virtual void SetBestHeight(int height) = 0;
- /**
- * Increment peer's misbehavior score. If the new value >= DISCOURAGEMENT_THRESHOLD, mark the node
- * to be discouraged, meaning the peer might be disconnected and added to the discouragement filter.
- * Public for unit testing.
- */
- virtual void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) = 0;
+ /* Public for unit testing. */
+ virtual void UnitTestMisbehaving(NodeId peer_id, int howmuch) = 0;
/**
* Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound.
diff --git a/src/netaddress.h b/src/netaddress.h
index 47ba045334..e52beb783d 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -9,7 +9,7 @@
#include <config/bitcoin-config.h>
#endif
-#include <compat.h>
+#include <compat/compat.h>
#include <crypto/siphash.h>
#include <prevector.h>
#include <random.h>
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 030f462ed9..a5f7bda875 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -5,7 +5,7 @@
#include <netbase.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <sync.h>
#include <tinyformat.h>
#include <util/sock.h>
@@ -387,7 +387,7 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
return error("Error sending to proxy");
}
uint8_t pchRet1[2];
- if ((recvr = InterruptibleRecv(pchRet1, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
+ if (InterruptibleRecv(pchRet1, 2, g_socks5_recv_timeout, sock) != IntrRecvError::OK) {
LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
return false;
}
@@ -410,7 +410,7 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
}
LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
uint8_t pchRetA[2];
- if ((recvr = InterruptibleRecv(pchRetA, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
+ if (InterruptibleRecv(pchRetA, 2, g_socks5_recv_timeout, sock) != IntrRecvError::OK) {
return error("Error reading proxy authentication response");
}
if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
@@ -476,7 +476,7 @@ bool Socks5(const std::string& strDest, uint16_t port, const ProxyCredentials* a
if (recvr != IntrRecvError::OK) {
return error("Error reading from proxy");
}
- if ((recvr = InterruptibleRecv(pchRet3, 2, g_socks5_recv_timeout, sock)) != IntrRecvError::OK) {
+ if (InterruptibleRecv(pchRet3, 2, g_socks5_recv_timeout, sock) != IntrRecvError::OK) {
return error("Error reading from proxy");
}
LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
diff --git a/src/netbase.h b/src/netbase.h
index bf7522210d..fadc8b418e 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -9,7 +9,7 @@
#include <config/bitcoin-config.h>
#endif
-#include <compat.h>
+#include <compat/compat.h>
#include <netaddress.h>
#include <serialize.h>
#include <util/sock.h>
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index cadafcaa8d..57f81e6bb6 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -21,6 +21,7 @@
#include <util/system.h>
#include <validation.h>
+#include <map>
#include <unordered_map>
namespace node {
@@ -414,7 +415,7 @@ void CleanupBlockRevFiles()
// Remove the rev files immediately and insert the blk file paths into an
// ordered map keyed by block file index.
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
- fs::path blocksdir = gArgs.GetBlocksDirPath();
+ const fs::path& blocksdir = gArgs.GetBlocksDirPath();
for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
const std::string path = fs::PathToString(it->path().filename());
if (fs::is_regular_file(*it) &&
@@ -471,7 +472,7 @@ static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const
fileout << blockundo;
// calculate & write checksum
- CHashWriter hasher(SER_GETHASH, PROTOCOL_VERSION);
+ HashWriter hasher{};
hasher << hashBlock;
hasher << blockundo;
fileout << hasher.GetHash();
@@ -823,7 +824,7 @@ struct CImportingNow {
}
};
-void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args)
+void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args, const fs::path& mempool_path)
{
SetSyscallSandboxPolicy(SyscallSandboxPolicy::INITIALIZATION_LOAD_BLOCKS);
ScheduleBatchPriority();
@@ -834,6 +835,9 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
// -reindex
if (fReindex) {
int nFile = 0;
+ // Map of disk positions for blocks with unknown parent (only used for reindex);
+ // parent hash -> child disk position, multiple children can have the same parent.
+ std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
while (true) {
FlatFilePos pos(nFile, 0);
if (!fs::exists(GetBlockPosFilename(pos))) {
@@ -844,7 +848,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
break; // This error is logged in OpenBlockFile
}
LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
- chainman.ActiveChainstate().LoadExternalBlockFile(file, &pos);
+ chainman.ActiveChainstate().LoadExternalBlockFile(file, &pos, &blocks_with_unknown_parent);
if (ShutdownRequested()) {
LogPrintf("Shutdown requested. Exit %s\n", __func__);
return;
@@ -878,7 +882,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
// We can't hold cs_main during ActivateBestChain even though we're accessing
// the chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve
// the relevant pointers before the ABC call.
- for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
+ for (Chainstate* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
BlockValidationState state;
if (!chainstate->ActivateBestChain(state, nullptr)) {
LogPrintf("Failed to connect best block (%s)\n", state.ToString());
@@ -893,6 +897,6 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
return;
}
} // End scope of CImportingNow
- chainman.ActiveChainstate().LoadMempool(args);
+ chainman.ActiveChainstate().LoadMempool(mempool_path);
}
} // namespace node
diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h
index e017f3f427..37d74ed102 100644
--- a/src/node/blockstorage.h
+++ b/src/node/blockstorage.h
@@ -26,7 +26,7 @@ class CBlockFileInfo;
class CBlockUndo;
class CChain;
class CChainParams;
-class CChainState;
+class Chainstate;
class ChainstateManager;
struct CCheckpointData;
struct FlatFilePos;
@@ -75,12 +75,12 @@ struct PruneLockInfo {
* Maintains a tree of blocks (stored in `m_block_index`) which is consulted
* to determine where the most-work tip is.
*
- * This data is used mostly in `CChainState` - information about, e.g.,
+ * This data is used mostly in `Chainstate` - information about, e.g.,
* candidate tips is not maintained here.
*/
class BlockManager
{
- friend CChainState;
+ friend Chainstate;
friend ChainstateManager;
private:
@@ -211,7 +211,7 @@ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, c
bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
-void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args);
+void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args, const fs::path& mempool_path);
} // namespace node
#endif // BITCOIN_NODE_BLOCKSTORAGE_H
diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp
index 54ba5b7966..3f1d6dd743 100644
--- a/src/node/chainstate.cpp
+++ b/src/node/chainstate.cpp
@@ -4,66 +4,90 @@
#include <node/chainstate.h>
+#include <chain.h>
+#include <coins.h>
#include <consensus/params.h>
#include <node/blockstorage.h>
+#include <node/caches.h>
+#include <sync.h>
+#include <threadsafety.h>
+#include <tinyformat.h>
+#include <txdb.h>
+#include <uint256.h>
+#include <util/time.h>
+#include <util/translation.h>
#include <validation.h>
+#include <algorithm>
+#include <atomic>
+#include <cassert>
+#include <memory>
+#include <vector>
+
namespace node {
-std::optional<ChainstateLoadingError> LoadChainstate(bool fReset,
- ChainstateManager& chainman,
- CTxMemPool* mempool,
- bool fPruneMode,
- bool fReindexChainState,
- int64_t nBlockTreeDBCache,
- int64_t nCoinDBCache,
- int64_t nCoinCacheUsage,
- bool block_tree_db_in_memory,
- bool coins_db_in_memory,
- std::function<bool()> shutdown_requested,
- std::function<void()> coins_error_cb)
+ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes,
+ const ChainstateLoadOptions& options)
{
- auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
- return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull();
+ auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
};
+ if (!hashAssumeValid.IsNull()) {
+ LogPrintf("Assuming ancestors of block %s have valid signatures.\n", hashAssumeValid.GetHex());
+ } else {
+ LogPrintf("Validating signatures for all blocks.\n");
+ }
+ LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex());
+ if (nMinimumChainWork < UintToArith256(chainman.GetConsensus().nMinimumChainWork)) {
+ LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainman.GetConsensus().nMinimumChainWork.GetHex());
+ }
+ if (nPruneTarget == std::numeric_limits<uint64_t>::max()) {
+ LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
+ } else if (nPruneTarget) {
+ LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);
+ }
+
LOCK(cs_main);
- chainman.InitializeChainstate(mempool);
- chainman.m_total_coinstip_cache = nCoinCacheUsage;
- chainman.m_total_coinsdb_cache = nCoinDBCache;
+ chainman.InitializeChainstate(options.mempool);
+ chainman.m_total_coinstip_cache = cache_sizes.coins;
+ chainman.m_total_coinsdb_cache = cache_sizes.coins_db;
auto& pblocktree{chainman.m_blockman.m_block_tree_db};
// new CBlockTreeDB tries to delete the existing file, which
// fails if it's still open from the previous loop. Close it first:
pblocktree.reset();
- pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, block_tree_db_in_memory, fReset));
+ pblocktree.reset(new CBlockTreeDB(cache_sizes.block_tree_db, options.block_tree_db_in_memory, options.reindex));
- if (fReset) {
+ if (options.reindex) {
pblocktree->WriteReindexing(true);
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files
- if (fPruneMode)
+ if (options.prune) {
CleanupBlockRevFiles();
+ }
}
- if (shutdown_requested && shutdown_requested()) return ChainstateLoadingError::SHUTDOWN_PROBED;
+ if (options.check_interrupt && options.check_interrupt()) return {ChainstateLoadStatus::INTERRUPTED, {}};
// LoadBlockIndex will load m_have_pruned if we've ever removed a
// block file from disk.
- // Note that it also sets fReindex based on the disk flag!
- // From here on out fReindex and fReset mean something different!
+ // Note that it also sets fReindex global based on the disk flag!
+ // From here on, fReindex and options.reindex values may be different!
if (!chainman.LoadBlockIndex()) {
- if (shutdown_requested && shutdown_requested()) return ChainstateLoadingError::SHUTDOWN_PROBED;
- return ChainstateLoadingError::ERROR_LOADING_BLOCK_DB;
+ if (options.check_interrupt && options.check_interrupt()) return {ChainstateLoadStatus::INTERRUPTED, {}};
+ return {ChainstateLoadStatus::FAILURE, _("Error loading block database")};
}
if (!chainman.BlockIndex().empty() &&
!chainman.m_blockman.LookupBlockIndex(chainman.GetConsensus().hashGenesisBlock)) {
- return ChainstateLoadingError::ERROR_BAD_GENESIS_BLOCK;
+ // If the loaded chain has a wrong genesis, bail out immediately
+ // (we're likely using a testnet datadir, or the other way around).
+ return {ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB, _("Incorrect or no genesis block found. Wrong datadir for network?")};
}
// Check for changed -prune state. What we are concerned about is a user who has pruned blocks
// in the past, but is now trying to run unpruned.
- if (chainman.m_blockman.m_have_pruned && !fPruneMode) {
- return ChainstateLoadingError::ERROR_PRUNED_NEEDS_REINDEX;
+ if (chainman.m_blockman.m_have_pruned && !options.prune) {
+ return {ChainstateLoadStatus::FAILURE, _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain")};
}
// At this point blocktree args are consistent with what's on disk.
@@ -71,85 +95,86 @@ std::optional<ChainstateLoadingError> LoadChainstate(bool fReset,
// (otherwise we use the one already on disk).
// This is called again in ThreadImport after the reindex completes.
if (!fReindex && !chainman.ActiveChainstate().LoadGenesisBlock()) {
- return ChainstateLoadingError::ERROR_LOAD_GENESIS_BLOCK_FAILED;
+ return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
}
// At this point we're either in reindex or we've loaded a useful
// block tree into BlockIndex()!
- for (CChainState* chainstate : chainman.GetAll()) {
+ for (Chainstate* chainstate : chainman.GetAll()) {
chainstate->InitCoinsDB(
- /*cache_size_bytes=*/nCoinDBCache,
- /*in_memory=*/coins_db_in_memory,
- /*should_wipe=*/fReset || fReindexChainState);
+ /*cache_size_bytes=*/cache_sizes.coins_db,
+ /*in_memory=*/options.coins_db_in_memory,
+ /*should_wipe=*/options.reindex || options.reindex_chainstate);
- if (coins_error_cb) {
- chainstate->CoinsErrorCatcher().AddReadErrCallback(coins_error_cb);
+ if (options.coins_error_cb) {
+ chainstate->CoinsErrorCatcher().AddReadErrCallback(options.coins_error_cb);
}
// Refuse to load unsupported database format.
// This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
if (chainstate->CoinsDB().NeedsUpgrade()) {
- return ChainstateLoadingError::ERROR_CHAINSTATE_UPGRADE_FAILED;
+ return {ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB, _("Unsupported chainstate database format found. "
+ "Please restart with -reindex-chainstate. This will "
+ "rebuild the chainstate database.")};
}
// ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
if (!chainstate->ReplayBlocks()) {
- return ChainstateLoadingError::ERROR_REPLAYBLOCKS_FAILED;
+ return {ChainstateLoadStatus::FAILURE, _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.")};
}
// The on-disk coinsdb is now in a good state, create the cache
- chainstate->InitCoinsCache(nCoinCacheUsage);
+ chainstate->InitCoinsCache(cache_sizes.coins);
assert(chainstate->CanFlushToDisk());
if (!is_coinsview_empty(chainstate)) {
// LoadChainTip initializes the chain based on CoinsTip()'s best block
if (!chainstate->LoadChainTip()) {
- return ChainstateLoadingError::ERROR_LOADCHAINTIP_FAILED;
+ return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
}
assert(chainstate->m_chain.Tip() != nullptr);
}
}
- if (!fReset) {
+ if (!options.reindex) {
auto chainstates{chainman.GetAll()};
if (std::any_of(chainstates.begin(), chainstates.end(),
- [](const CChainState* cs) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return cs->NeedsRedownload(); })) {
- return ChainstateLoadingError::ERROR_BLOCKS_WITNESS_INSUFFICIENTLY_VALIDATED;
- }
+ [](const Chainstate* cs) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return cs->NeedsRedownload(); })) {
+ return {ChainstateLoadStatus::FAILURE, strprintf(_("Witness data for blocks after height %d requires validation. Please restart with -reindex."),
+ chainman.GetConsensus().SegwitHeight)};
+ };
}
- return std::nullopt;
+ return {ChainstateLoadStatus::SUCCESS, {}};
}
-std::optional<ChainstateLoadVerifyError> VerifyLoadedChainstate(ChainstateManager& chainman,
- bool fReset,
- bool fReindexChainState,
- int check_blocks,
- int check_level)
+ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options)
{
- auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
- return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull();
+ auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
};
LOCK(cs_main);
- for (CChainState* chainstate : chainman.GetAll()) {
+ for (Chainstate* chainstate : chainman.GetAll()) {
if (!is_coinsview_empty(chainstate)) {
const CBlockIndex* tip = chainstate->m_chain.Tip();
if (tip && tip->nTime > GetTime() + MAX_FUTURE_BLOCK_TIME) {
- return ChainstateLoadVerifyError::ERROR_BLOCK_FROM_FUTURE;
+ return {ChainstateLoadStatus::FAILURE, _("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")};
}
if (!CVerifyDB().VerifyDB(
*chainstate, chainman.GetConsensus(), chainstate->CoinsDB(),
- check_level,
- check_blocks)) {
- return ChainstateLoadVerifyError::ERROR_CORRUPTED_BLOCK_DB;
+ options.check_level,
+ options.check_blocks)) {
+ return {ChainstateLoadStatus::FAILURE, _("Corrupted block database detected")};
}
}
}
- return std::nullopt;
+ return {ChainstateLoadStatus::SUCCESS, {}};
}
} // namespace node
diff --git a/src/node/chainstate.h b/src/node/chainstate.h
index ff7935e8e0..2289310ece 100644
--- a/src/node/chainstate.h
+++ b/src/node/chainstate.h
@@ -5,30 +5,41 @@
#ifndef BITCOIN_NODE_CHAINSTATE_H
#define BITCOIN_NODE_CHAINSTATE_H
+#include <util/translation.h>
+#include <validation.h>
+
#include <cstdint>
#include <functional>
-#include <optional>
+#include <tuple>
-class ChainstateManager;
class CTxMemPool;
-namespace Consensus {
-struct Params;
-} // namespace Consensus
namespace node {
-enum class ChainstateLoadingError {
- ERROR_LOADING_BLOCK_DB,
- ERROR_BAD_GENESIS_BLOCK,
- ERROR_PRUNED_NEEDS_REINDEX,
- ERROR_LOAD_GENESIS_BLOCK_FAILED,
- ERROR_CHAINSTATE_UPGRADE_FAILED,
- ERROR_REPLAYBLOCKS_FAILED,
- ERROR_LOADCHAINTIP_FAILED,
- ERROR_GENERIC_BLOCKDB_OPEN_FAILED,
- ERROR_BLOCKS_WITNESS_INSUFFICIENTLY_VALIDATED,
- SHUTDOWN_PROBED,
+
+struct CacheSizes;
+
+struct ChainstateLoadOptions {
+ CTxMemPool* mempool{nullptr};
+ bool block_tree_db_in_memory{false};
+ bool coins_db_in_memory{false};
+ bool reindex{false};
+ bool reindex_chainstate{false};
+ bool prune{false};
+ int64_t check_blocks{DEFAULT_CHECKBLOCKS};
+ int64_t check_level{DEFAULT_CHECKLEVEL};
+ std::function<bool()> check_interrupt;
+ std::function<void()> coins_error_cb;
};
+//! Chainstate load status. Simple applications can just check for the success
+//! case, and treat other cases as errors. More complex applications may want to
+//! try reindexing in the generic failure case, and pass an interrupt callback
+//! and exit cleanly in the interrupted case.
+enum class ChainstateLoadStatus { SUCCESS, FAILURE, FAILURE_INCOMPATIBLE_DB, INTERRUPTED };
+
+//! Chainstate load status code and optional error string.
+using ChainstateLoadResult = std::tuple<ChainstateLoadStatus, bilingual_str>;
+
/** This sequence can have 4 types of outcomes:
*
* 1. Success
@@ -40,45 +51,11 @@ enum class ChainstateLoadingError {
* 4. Hard failure
* - a failure that definitively cannot be recovered from with a reindex
*
- * Currently, LoadChainstate returns a std::optional<ChainstateLoadingError>
- * which:
- *
- * - if has_value()
- * - Either "Soft failure", "Hard failure", or "Shutdown requested",
- * differentiable by the specific enumerator.
- *
- * Note that a return value of SHUTDOWN_PROBED means ONLY that "during
- * this sequence, when we explicitly checked shutdown_requested() at
- * arbitrary points, one of those calls returned true". Therefore, a
- * return value other than SHUTDOWN_PROBED does not guarantee that
- * shutdown hasn't been called indirectly.
- * - else
- * - Success!
+ * LoadChainstate returns a (status code, error string) tuple.
*/
-std::optional<ChainstateLoadingError> LoadChainstate(bool fReset,
- ChainstateManager& chainman,
- CTxMemPool* mempool,
- bool fPruneMode,
- bool fReindexChainState,
- int64_t nBlockTreeDBCache,
- int64_t nCoinDBCache,
- int64_t nCoinCacheUsage,
- bool block_tree_db_in_memory,
- bool coins_db_in_memory,
- std::function<bool()> shutdown_requested = nullptr,
- std::function<void()> coins_error_cb = nullptr);
-
-enum class ChainstateLoadVerifyError {
- ERROR_BLOCK_FROM_FUTURE,
- ERROR_CORRUPTED_BLOCK_DB,
- ERROR_GENERIC_FAILURE,
-};
-
-std::optional<ChainstateLoadVerifyError> VerifyLoadedChainstate(ChainstateManager& chainman,
- bool fReset,
- bool fReindexChainState,
- int check_blocks,
- int check_level);
+ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSizes& cache_sizes,
+ const ChainstateLoadOptions& options);
+ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options);
} // namespace node
#endif // BITCOIN_NODE_CHAINSTATE_H
diff --git a/src/node/connection_types.cpp b/src/node/connection_types.cpp
new file mode 100644
index 0000000000..904f4371aa
--- /dev/null
+++ b/src/node/connection_types.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <node/connection_types.h>
+#include <cassert>
+
+std::string ConnectionTypeAsString(ConnectionType conn_type)
+{
+ switch (conn_type) {
+ case ConnectionType::INBOUND:
+ return "inbound";
+ case ConnectionType::MANUAL:
+ return "manual";
+ case ConnectionType::FEELER:
+ return "feeler";
+ case ConnectionType::OUTBOUND_FULL_RELAY:
+ return "outbound-full-relay";
+ case ConnectionType::BLOCK_RELAY:
+ return "block-relay-only";
+ case ConnectionType::ADDR_FETCH:
+ return "addr-fetch";
+ } // no default case, so the compiler can warn about missing cases
+
+ assert(false);
+}
diff --git a/src/node/connection_types.h b/src/node/connection_types.h
new file mode 100644
index 0000000000..5e1abcace6
--- /dev/null
+++ b/src/node/connection_types.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_CONNECTION_TYPES_H
+#define BITCOIN_NODE_CONNECTION_TYPES_H
+
+#include <string>
+
+/** Different types of connections to a peer. This enum encapsulates the
+ * information we have available at the time of opening or accepting the
+ * connection. Aside from INBOUND, all types are initiated by us.
+ *
+ * If adding or removing types, please update CONNECTION_TYPE_DOC in
+ * src/rpc/net.cpp and src/qt/rpcconsole.cpp, as well as the descriptions in
+ * src/qt/guiutil.cpp and src/bitcoin-cli.cpp::NetinfoRequestHandler. */
+enum class ConnectionType {
+ /**
+ * Inbound connections are those initiated by a peer. This is the only
+ * property we know at the time of connection, until P2P messages are
+ * exchanged.
+ */
+ INBOUND,
+
+ /**
+ * These are the default connections that we use to connect with the
+ * network. There is no restriction on what is relayed; by default we relay
+ * blocks, addresses & transactions. We automatically attempt to open
+ * MAX_OUTBOUND_FULL_RELAY_CONNECTIONS using addresses from our AddrMan.
+ */
+ OUTBOUND_FULL_RELAY,
+
+
+ /**
+ * We open manual connections to addresses that users explicitly requested
+ * via the addnode RPC or the -addnode/-connect configuration options. Even if a
+ * manual connection is misbehaving, we do not automatically disconnect or
+ * add it to our discouragement filter.
+ */
+ MANUAL,
+
+ /**
+ * Feeler connections are short-lived connections made to check that a node
+ * is alive. They can be useful for:
+ * - test-before-evict: if one of the peers is considered for eviction from
+ * our AddrMan because another peer is mapped to the same slot in the tried table,
+ * evict only if this longer-known peer is offline.
+ * - move node addresses from New to Tried table, so that we have more
+ * connectable addresses in our AddrMan.
+ * Note that in the literature ("Eclipse Attacks on Bitcoin’s Peer-to-Peer Network")
+ * only the latter feature is referred to as "feeler connections",
+ * although in our codebase feeler connections encompass test-before-evict as well.
+ * We make these connections approximately every FEELER_INTERVAL:
+ * first we resolve previously found collisions if they exist (test-before-evict),
+ * otherwise we connect to a node from the new table.
+ */
+ FEELER,
+
+ /**
+ * We use block-relay-only connections to help prevent against partition
+ * attacks. By not relaying transactions or addresses, these connections
+ * are harder to detect by a third party, thus helping obfuscate the
+ * network topology. We automatically attempt to open
+ * MAX_BLOCK_RELAY_ONLY_ANCHORS using addresses from our anchors.dat. Then
+ * addresses from our AddrMan if MAX_BLOCK_RELAY_ONLY_CONNECTIONS
+ * isn't reached yet.
+ */
+ BLOCK_RELAY,
+
+ /**
+ * AddrFetch connections are short lived connections used to solicit
+ * addresses from peers. These are initiated to addresses submitted via the
+ * -seednode command line argument, or under certain conditions when the
+ * AddrMan is empty.
+ */
+ ADDR_FETCH,
+};
+
+/** Convert ConnectionType enum to a string value */
+std::string ConnectionTypeAsString(ConnectionType conn_type);
+
+#endif // BITCOIN_NODE_CONNECTION_TYPES_H
diff --git a/src/node/eviction.cpp b/src/node/eviction.cpp
new file mode 100644
index 0000000000..33406931d4
--- /dev/null
+++ b/src/node/eviction.cpp
@@ -0,0 +1,240 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <node/eviction.h>
+
+#include <algorithm>
+#include <array>
+#include <chrono>
+#include <cstdint>
+#include <functional>
+#include <map>
+#include <vector>
+
+
+static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
+{
+ return a.m_min_ping_time > b.m_min_ping_time;
+}
+
+static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
+{
+ return a.m_connected > b.m_connected;
+}
+
+static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) {
+ return a.nKeyedNetGroup < b.nKeyedNetGroup;
+}
+
+static bool CompareNodeBlockTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
+{
+ // There is a fall-through here because it is common for a node to have many peers which have not yet relayed a block.
+ if (a.m_last_block_time != b.m_last_block_time) return a.m_last_block_time < b.m_last_block_time;
+ if (a.fRelevantServices != b.fRelevantServices) return b.fRelevantServices;
+ return a.m_connected > b.m_connected;
+}
+
+static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
+{
+ // There is a fall-through here because it is common for a node to have more than a few peers that have not yet relayed txn.
+ if (a.m_last_tx_time != b.m_last_tx_time) return a.m_last_tx_time < b.m_last_tx_time;
+ if (a.m_relay_txs != b.m_relay_txs) return b.m_relay_txs;
+ if (a.fBloomFilter != b.fBloomFilter) return a.fBloomFilter;
+ return a.m_connected > b.m_connected;
+}
+
+// Pick out the potential block-relay only peers, and sort them by last block time.
+static bool CompareNodeBlockRelayOnlyTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
+{
+ if (a.m_relay_txs != b.m_relay_txs) return a.m_relay_txs;
+ if (a.m_last_block_time != b.m_last_block_time) return a.m_last_block_time < b.m_last_block_time;
+ if (a.fRelevantServices != b.fRelevantServices) return b.fRelevantServices;
+ return a.m_connected > b.m_connected;
+}
+
+/**
+ * Sort eviction candidates by network/localhost and connection uptime.
+ * Candidates near the beginning are more likely to be evicted, and those
+ * near the end are more likely to be protected, e.g. less likely to be evicted.
+ * - First, nodes that are not `is_local` and that do not belong to `network`,
+ * sorted by increasing uptime (from most recently connected to connected longer).
+ * - Then, nodes that are `is_local` or belong to `network`, sorted by increasing uptime.
+ */
+struct CompareNodeNetworkTime {
+ const bool m_is_local;
+ const Network m_network;
+ CompareNodeNetworkTime(bool is_local, Network network) : m_is_local(is_local), m_network(network) {}
+ bool operator()(const NodeEvictionCandidate& a, const NodeEvictionCandidate& b) const
+ {
+ if (m_is_local && a.m_is_local != b.m_is_local) return b.m_is_local;
+ if ((a.m_network == m_network) != (b.m_network == m_network)) return b.m_network == m_network;
+ return a.m_connected > b.m_connected;
+ };
+};
+
+//! Sort an array by the specified comparator, then erase the last K elements where predicate is true.
+template <typename T, typename Comparator>
+static void EraseLastKElements(
+ std::vector<T>& elements, Comparator comparator, size_t k,
+ std::function<bool(const NodeEvictionCandidate&)> predicate = [](const NodeEvictionCandidate& n) { return true; })
+{
+ std::sort(elements.begin(), elements.end(), comparator);
+ size_t eraseSize = std::min(k, elements.size());
+ elements.erase(std::remove_if(elements.end() - eraseSize, elements.end(), predicate), elements.end());
+}
+
+void ProtectNoBanConnections(std::vector<NodeEvictionCandidate>& eviction_candidates)
+{
+ eviction_candidates.erase(std::remove_if(eviction_candidates.begin(), eviction_candidates.end(),
+ [](NodeEvictionCandidate const& n) {
+ return n.m_noban;
+ }),
+ eviction_candidates.end());
+}
+
+void ProtectOutboundConnections(std::vector<NodeEvictionCandidate>& eviction_candidates)
+{
+ eviction_candidates.erase(std::remove_if(eviction_candidates.begin(), eviction_candidates.end(),
+ [](NodeEvictionCandidate const& n) {
+ return n.m_conn_type != ConnectionType::INBOUND;
+ }),
+ eviction_candidates.end());
+}
+
+void ProtectEvictionCandidatesByRatio(std::vector<NodeEvictionCandidate>& eviction_candidates)
+{
+ // Protect the half of the remaining nodes which have been connected the longest.
+ // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
+ // To favorise the diversity of our peer connections, reserve up to half of these protected
+ // spots for Tor/onion, localhost, I2P, and CJDNS peers, even if they're not longest uptime
+ // overall. This helps protect these higher-latency peers that tend to be otherwise
+ // disadvantaged under our eviction criteria.
+ const size_t initial_size = eviction_candidates.size();
+ const size_t total_protect_size{initial_size / 2};
+
+ // Disadvantaged networks to protect. In the case of equal counts, earlier array members
+ // have the first opportunity to recover unused slots from the previous iteration.
+ struct Net { bool is_local; Network id; size_t count; };
+ std::array<Net, 4> networks{
+ {{false, NET_CJDNS, 0}, {false, NET_I2P, 0}, {/*localhost=*/true, NET_MAX, 0}, {false, NET_ONION, 0}}};
+
+ // Count and store the number of eviction candidates per network.
+ for (Net& n : networks) {
+ n.count = std::count_if(eviction_candidates.cbegin(), eviction_candidates.cend(),
+ [&n](const NodeEvictionCandidate& c) {
+ return n.is_local ? c.m_is_local : c.m_network == n.id;
+ });
+ }
+ // Sort `networks` by ascending candidate count, to give networks having fewer candidates
+ // the first opportunity to recover unused protected slots from the previous iteration.
+ std::stable_sort(networks.begin(), networks.end(), [](Net a, Net b) { return a.count < b.count; });
+
+ // Protect up to 25% of the eviction candidates by disadvantaged network.
+ const size_t max_protect_by_network{total_protect_size / 2};
+ size_t num_protected{0};
+
+ while (num_protected < max_protect_by_network) {
+ // Count the number of disadvantaged networks from which we have peers to protect.
+ auto num_networks = std::count_if(networks.begin(), networks.end(), [](const Net& n) { return n.count; });
+ if (num_networks == 0) {
+ break;
+ }
+ const size_t disadvantaged_to_protect{max_protect_by_network - num_protected};
+ const size_t protect_per_network{std::max(disadvantaged_to_protect / num_networks, static_cast<size_t>(1))};
+ // Early exit flag if there are no remaining candidates by disadvantaged network.
+ bool protected_at_least_one{false};
+
+ for (Net& n : networks) {
+ if (n.count == 0) continue;
+ const size_t before = eviction_candidates.size();
+ EraseLastKElements(eviction_candidates, CompareNodeNetworkTime(n.is_local, n.id),
+ protect_per_network, [&n](const NodeEvictionCandidate& c) {
+ return n.is_local ? c.m_is_local : c.m_network == n.id;
+ });
+ const size_t after = eviction_candidates.size();
+ if (before > after) {
+ protected_at_least_one = true;
+ const size_t delta{before - after};
+ num_protected += delta;
+ if (num_protected >= max_protect_by_network) {
+ break;
+ }
+ n.count -= delta;
+ }
+ }
+ if (!protected_at_least_one) {
+ break;
+ }
+ }
+
+ // Calculate how many we removed, and update our total number of peers that
+ // we want to protect based on uptime accordingly.
+ assert(num_protected == initial_size - eviction_candidates.size());
+ const size_t remaining_to_protect{total_protect_size - num_protected};
+ EraseLastKElements(eviction_candidates, ReverseCompareNodeTimeConnected, remaining_to_protect);
+}
+
+[[nodiscard]] std::optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
+{
+ // Protect connections with certain characteristics
+
+ ProtectNoBanConnections(vEvictionCandidates);
+
+ ProtectOutboundConnections(vEvictionCandidates);
+
+ // Deterministically select 4 peers to protect by netgroup.
+ // An attacker cannot predict which netgroups will be protected
+ EraseLastKElements(vEvictionCandidates, CompareNetGroupKeyed, 4);
+ // Protect the 8 nodes with the lowest minimum ping time.
+ // An attacker cannot manipulate this metric without physically moving nodes closer to the target.
+ EraseLastKElements(vEvictionCandidates, ReverseCompareNodeMinPingTime, 8);
+ // Protect 4 nodes that most recently sent us novel transactions accepted into our mempool.
+ // An attacker cannot manipulate this metric without performing useful work.
+ EraseLastKElements(vEvictionCandidates, CompareNodeTXTime, 4);
+ // Protect up to 8 non-tx-relay peers that have sent us novel blocks.
+ EraseLastKElements(vEvictionCandidates, CompareNodeBlockRelayOnlyTime, 8,
+ [](const NodeEvictionCandidate& n) { return !n.m_relay_txs && n.fRelevantServices; });
+
+ // Protect 4 nodes that most recently sent us novel blocks.
+ // An attacker cannot manipulate this metric without performing useful work.
+ EraseLastKElements(vEvictionCandidates, CompareNodeBlockTime, 4);
+
+ // Protect some of the remaining eviction candidates by ratios of desirable
+ // or disadvantaged characteristics.
+ ProtectEvictionCandidatesByRatio(vEvictionCandidates);
+
+ if (vEvictionCandidates.empty()) return std::nullopt;
+
+ // If any remaining peers are preferred for eviction consider only them.
+ // This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
+ // then we probably don't want to evict it no matter what.
+ if (std::any_of(vEvictionCandidates.begin(),vEvictionCandidates.end(),[](NodeEvictionCandidate const &n){return n.prefer_evict;})) {
+ vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.begin(),vEvictionCandidates.end(),
+ [](NodeEvictionCandidate const &n){return !n.prefer_evict;}),vEvictionCandidates.end());
+ }
+
+ // Identify the network group with the most connections and youngest member.
+ // (vEvictionCandidates is already sorted by reverse connect time)
+ uint64_t naMostConnections;
+ unsigned int nMostConnections = 0;
+ std::chrono::seconds nMostConnectionsTime{0};
+ std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapNetGroupNodes;
+ for (const NodeEvictionCandidate &node : vEvictionCandidates) {
+ std::vector<NodeEvictionCandidate> &group = mapNetGroupNodes[node.nKeyedNetGroup];
+ group.push_back(node);
+ const auto grouptime{group[0].m_connected};
+
+ if (group.size() > nMostConnections || (group.size() == nMostConnections && grouptime > nMostConnectionsTime)) {
+ nMostConnections = group.size();
+ nMostConnectionsTime = grouptime;
+ naMostConnections = node.nKeyedNetGroup;
+ }
+ }
+
+ // Reduce to the network group with the most connections
+ vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
+
+ // Disconnect from the network group with the most connections
+ return vEvictionCandidates.front().id;
+}
diff --git a/src/node/eviction.h b/src/node/eviction.h
new file mode 100644
index 0000000000..1bb32e5327
--- /dev/null
+++ b/src/node/eviction.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_EVICTION_H
+#define BITCOIN_NODE_EVICTION_H
+
+#include <node/connection_types.h>
+#include <net_permissions.h>
+
+#include <chrono>
+#include <cstdint>
+#include <optional>
+#include <vector>
+
+typedef int64_t NodeId;
+
+struct NodeEvictionCandidate {
+ NodeId id;
+ std::chrono::seconds m_connected;
+ std::chrono::microseconds m_min_ping_time;
+ std::chrono::seconds m_last_block_time;
+ std::chrono::seconds m_last_tx_time;
+ bool fRelevantServices;
+ bool m_relay_txs;
+ bool fBloomFilter;
+ uint64_t nKeyedNetGroup;
+ bool prefer_evict;
+ bool m_is_local;
+ Network m_network;
+ bool m_noban;
+ ConnectionType m_conn_type;
+};
+
+/**
+ * Select an inbound peer to evict after filtering out (protecting) peers having
+ * distinct, difficult-to-forge characteristics. The protection logic picks out
+ * fixed numbers of desirable peers per various criteria, followed by (mostly)
+ * ratios of desirable or disadvantaged peers. If any eviction candidates
+ * remain, the selection logic chooses a peer to evict.
+ */
+[[nodiscard]] std::optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates);
+
+/** Protect desirable or disadvantaged inbound peers from eviction by ratio.
+ *
+ * This function protects half of the peers which have been connected the
+ * longest, to replicate the non-eviction implicit behavior and preclude attacks
+ * that start later.
+ *
+ * Half of these protected spots (1/4 of the total) are reserved for the
+ * following categories of peers, sorted by longest uptime, even if they're not
+ * longest uptime overall:
+ *
+ * - onion peers connected via our tor control service
+ *
+ * - localhost peers, as manually configured hidden services not using
+ * `-bind=addr[:port]=onion` will not be detected as inbound onion connections
+ *
+ * - I2P peers
+ *
+ * - CJDNS peers
+ *
+ * This helps protect these privacy network peers, which tend to be otherwise
+ * disadvantaged under our eviction criteria for their higher min ping times
+ * relative to IPv4/IPv6 peers, and favorise the diversity of peer connections.
+ */
+void ProtectEvictionCandidatesByRatio(std::vector<NodeEvictionCandidate>& vEvictionCandidates);
+
+#endif // BITCOIN_NODE_EVICTION_H
diff --git a/src/node/interface_ui.cpp b/src/node/interface_ui.cpp
index 370cde84f8..fa90d6fda7 100644
--- a/src/node/interface_ui.cpp
+++ b/src/node/interface_ui.cpp
@@ -53,7 +53,7 @@ void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return
void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); }
void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); }
void CClientUIInterface::NotifyBlockTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(s, i); }
-void CClientUIInterface::NotifyHeaderTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyHeaderTip(s, i); }
+void CClientUIInterface::NotifyHeaderTip(SynchronizationState s, int64_t height, int64_t timestamp, bool presync) { return g_ui_signals.NotifyHeaderTip(s, height, timestamp, presync); }
void CClientUIInterface::BannedListChanged() { return g_ui_signals.BannedListChanged(); }
bool InitError(const bilingual_str& str)
diff --git a/src/node/interface_ui.h b/src/node/interface_ui.h
index 37c0f6392b..316d75167e 100644
--- a/src/node/interface_ui.h
+++ b/src/node/interface_ui.h
@@ -105,7 +105,7 @@ public:
ADD_SIGNALS_DECL_WRAPPER(NotifyBlockTip, void, SynchronizationState, const CBlockIndex*);
/** Best header has changed */
- ADD_SIGNALS_DECL_WRAPPER(NotifyHeaderTip, void, SynchronizationState, const CBlockIndex*);
+ ADD_SIGNALS_DECL_WRAPPER(NotifyHeaderTip, void, SynchronizationState, int64_t height, int64_t timestamp, bool presync);
/** Banlist did change. */
ADD_SIGNALS_DECL_WRAPPER(BannedListChanged, void, void);
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index 1905a4df29..aa7ddec770 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -19,6 +19,7 @@
#include <netaddress.h>
#include <netbase.h>
#include <node/blockstorage.h>
+#include <kernel/chain.h>
#include <node/coin.h>
#include <node/context.h>
#include <node/transaction.h>
@@ -35,7 +36,6 @@
#include <shutdown.h>
#include <support/allocators/secure.h>
#include <sync.h>
-#include <timedata.h>
#include <txmempool.h>
#include <uint256.h>
#include <univalue.h>
@@ -66,6 +66,8 @@ using interfaces::Node;
using interfaces::WalletLoader;
namespace node {
+// All members of the classes in this namespace are intentionally public, as the
+// classes themselves are private.
namespace {
#ifdef ENABLE_EXTERNAL_SIGNER
class ExternalSignerImpl : public interfaces::ExternalSigner
@@ -73,15 +75,12 @@ class ExternalSignerImpl : public interfaces::ExternalSigner
public:
ExternalSignerImpl(::ExternalSigner signer) : m_signer(std::move(signer)) {}
std::string getName() override { return m_signer.m_name; }
-private:
::ExternalSigner m_signer;
};
#endif
class NodeImpl : public Node
{
-private:
- ChainstateManager& chainman() { return *Assert(m_context->chainman); }
public:
explicit NodeImpl(NodeContext& context) { setContext(&context); }
void initLogging() override { InitLogging(*Assert(m_context->args)); }
@@ -288,12 +287,7 @@ public:
}
double getVerificationProgress() override
{
- const CBlockIndex* tip;
- {
- LOCK(::cs_main);
- tip = chainman().ActiveChain().Tip();
- }
- return GuessVerificationProgress(chainman().GetParams().TxData(), tip);
+ return GuessVerificationProgress(chainman().GetParams().TxData(), WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip()));
}
bool isInitialBlockDownload() override {
return chainman().ActiveChainstate().IsInitialBlockDownload();
@@ -307,7 +301,11 @@ public:
}
}
bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
- CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
+ CFeeRate getDustRelayFee() override
+ {
+ if (!m_context->mempool) return CFeeRate{DUST_RELAY_TX_FEE};
+ return m_context->mempool->m_dust_relay_feerate;
+ }
UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
{
JSONRPCRequest req;
@@ -379,9 +377,8 @@ public:
std::unique_ptr<Handler> handleNotifyHeaderTip(NotifyHeaderTipFn fn) override
{
return MakeHandler(
- ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
- fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()},
- /* verification progress is unused when a header was received */ 0);
+ ::uiInterface.NotifyHeaderTip_connect([fn](SynchronizationState sync_state, int64_t height, int64_t timestamp, bool presync) {
+ fn(sync_state, BlockTip{(int)height, timestamp, uint256{}}, presync);
}));
}
NodeContext* context() override { return m_context; }
@@ -389,6 +386,7 @@ public:
{
m_context = context;
}
+ ChainstateManager& chainman() { return *Assert(m_context->chainman); }
NodeContext* m_context{nullptr};
};
@@ -401,6 +399,7 @@ bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<Rec
if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax();
if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index;
+ if (block.m_locator) { *block.m_locator = GetLocator(index); }
if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active);
if (block.m_data) {
REVERSE_LOCK(lock);
@@ -426,11 +425,11 @@ public:
}
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
{
- m_notifications->blockConnected(*block, index->nHeight);
+ m_notifications->blockConnected(kernel::MakeBlockInfo(index, block.get()));
}
void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* index) override
{
- m_notifications->blockDisconnected(*block, index->nHeight);
+ m_notifications->blockDisconnected(kernel::MakeBlockInfo(index, block.get()));
}
void UpdatedBlockTip(const CBlockIndex* index, const CBlockIndex* fork_index, bool is_ibd) override
{
@@ -500,46 +499,39 @@ public:
class ChainImpl : public Chain
{
-private:
- ChainstateManager& chainman() { return *Assert(m_node.chainman); }
public:
explicit ChainImpl(NodeContext& node) : m_node(node) {}
std::optional<int> getHeight() override
{
- LOCK(::cs_main);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- int height = active.Height();
- if (height >= 0) {
- return height;
- }
- return std::nullopt;
+ const int height{WITH_LOCK(::cs_main, return chainman().ActiveChain().Height())};
+ return height >= 0 ? std::optional{height} : std::nullopt;
}
uint256 getBlockHash(int height) override
{
LOCK(::cs_main);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- CBlockIndex* block = active[height];
- assert(block);
- return block->GetBlockHash();
+ return Assert(chainman().ActiveChain()[height])->GetBlockHash();
}
bool haveBlockOnDisk(int height) override
{
- LOCK(cs_main);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- CBlockIndex* block = active[height];
+ LOCK(::cs_main);
+ const CBlockIndex* block{chainman().ActiveChain()[height]};
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
}
CBlockLocator getTipLocator() override
{
- LOCK(cs_main);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- return active.GetLocator();
+ LOCK(::cs_main);
+ return chainman().ActiveChain().GetLocator();
+ }
+ CBlockLocator getActiveChainLocator(const uint256& block_hash) override
+ {
+ LOCK(::cs_main);
+ const CBlockIndex* index = chainman().m_blockman.LookupBlockIndex(block_hash);
+ return GetLocator(index);
}
std::optional<int> findLocatorFork(const CBlockLocator& locator) override
{
- LOCK(cs_main);
- const CChainState& active = Assert(m_node.chainman)->ActiveChainstate();
- if (const CBlockIndex* fork = active.FindForkInGlobalIndex(locator)) {
+ LOCK(::cs_main);
+ if (const CBlockIndex* fork = chainman().ActiveChainstate().FindForkInGlobalIndex(locator)) {
return fork->nHeight;
}
return std::nullopt;
@@ -547,20 +539,19 @@ public:
bool findBlock(const uint256& hash, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- return FillBlock(m_node.chainman->m_blockman.LookupBlockIndex(hash), block, lock, active);
+ return FillBlock(chainman().m_blockman.LookupBlockIndex(hash), block, lock, chainman().ActiveChain());
}
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ const CChain& active = chainman().ActiveChain();
return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active);
}
bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
{
WAIT_LOCK(cs_main, lock);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- if (const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash)) {
+ const CChain& active = chainman().ActiveChain();
+ if (const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) {
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
return FillBlock(ancestor, ancestor_out, lock, active);
}
@@ -570,18 +561,17 @@ public:
bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
{
WAIT_LOCK(cs_main, lock);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- const CBlockIndex* block = m_node.chainman->m_blockman.LookupBlockIndex(block_hash);
- const CBlockIndex* ancestor = m_node.chainman->m_blockman.LookupBlockIndex(ancestor_hash);
+ const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash);
+ const CBlockIndex* ancestor = chainman().m_blockman.LookupBlockIndex(ancestor_hash);
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
- return FillBlock(ancestor, ancestor_out, lock, active);
+ return FillBlock(ancestor, ancestor_out, lock, chainman().ActiveChain());
}
bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
{
WAIT_LOCK(cs_main, lock);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- const CBlockIndex* block1 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash1);
- const CBlockIndex* block2 = m_node.chainman->m_blockman.LookupBlockIndex(block_hash2);
+ const CChain& active = chainman().ActiveChain();
+ const CBlockIndex* block1 = chainman().m_blockman.LookupBlockIndex(block_hash1);
+ const CBlockIndex* block2 = chainman().m_blockman.LookupBlockIndex(block_hash2);
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
// Using & instead of && below to avoid short circuiting and leaving
// output uninitialized. Cast bool to int to avoid -Wbitwise-instead-of-logical
@@ -593,7 +583,7 @@ public:
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
double guessVerificationProgress(const uint256& block_hash) override
{
- LOCK(cs_main);
+ LOCK(::cs_main);
return GuessVerificationProgress(chainman().GetParams().TxData(), chainman().m_blockman.LookupBlockIndex(block_hash));
}
bool hasBlocks(const uint256& block_hash, int min_height, std::optional<int> max_height) override
@@ -653,8 +643,12 @@ public:
}
void getPackageLimits(unsigned int& limit_ancestor_count, unsigned int& limit_descendant_count) override
{
- limit_ancestor_count = gArgs.GetIntArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
- limit_descendant_count = gArgs.GetIntArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
+ const CTxMemPool::Limits default_limits{};
+
+ const CTxMemPool::Limits& limits{m_node.mempool ? m_node.mempool->m_limits : default_limits};
+
+ limit_ancestor_count = limits.ancestor_count;
+ limit_descendant_count = limits.descendant_count;
}
bool checkChainLimits(const CTransactionRef& tx) override
{
@@ -662,15 +656,12 @@ public:
LockPoints lp;
CTxMemPoolEntry entry(tx, 0, 0, 0, false, 0, lp);
CTxMemPool::setEntries ancestors;
- auto limit_ancestor_count = gArgs.GetIntArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
- auto limit_ancestor_size = gArgs.GetIntArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000;
- auto limit_descendant_count = gArgs.GetIntArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT);
- auto limit_descendant_size = gArgs.GetIntArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000;
+ const CTxMemPool::Limits& limits{m_node.mempool->m_limits};
std::string unused_error_string;
LOCK(m_node.mempool->cs);
return m_node.mempool->CalculateMemPoolAncestors(
- entry, ancestors, limit_ancestor_count, limit_ancestor_size,
- limit_descendant_count, limit_descendant_size, unused_error_string);
+ entry, ancestors, limits.ancestor_count, limits.ancestor_size_vbytes,
+ limits.descendant_count, limits.descendant_size_vbytes, unused_error_string);
}
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
{
@@ -685,15 +676,27 @@ public:
CFeeRate mempoolMinFee() override
{
if (!m_node.mempool) return {};
- return m_node.mempool->GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
+ return m_node.mempool->GetMinFee();
+ }
+ CFeeRate relayMinFee() override
+ {
+ if (!m_node.mempool) return CFeeRate{DEFAULT_MIN_RELAY_TX_FEE};
+ return m_node.mempool->m_min_relay_feerate;
+ }
+ CFeeRate relayIncrementalFee() override
+ {
+ if (!m_node.mempool) return CFeeRate{DEFAULT_INCREMENTAL_RELAY_FEE};
+ return m_node.mempool->m_incremental_relay_feerate;
+ }
+ CFeeRate relayDustFee() override
+ {
+ if (!m_node.mempool) return CFeeRate{DUST_RELAY_TX_FEE};
+ return m_node.mempool->m_dust_relay_feerate;
}
- CFeeRate relayMinFee() override { return ::minRelayTxFee; }
- CFeeRate relayIncrementalFee() override { return ::incrementalRelayFee; }
- CFeeRate relayDustFee() override { return ::dustRelayFee; }
bool havePruned() override
{
- LOCK(cs_main);
- return m_node.chainman->m_blockman.m_have_pruned;
+ LOCK(::cs_main);
+ return chainman().m_blockman.m_have_pruned;
}
bool isReadyToBroadcast() override { return !node::fImporting && !node::fReindex && !isInitialBlockDownload(); }
bool isInitialBlockDownload() override {
@@ -713,11 +716,7 @@ public:
}
void waitForNotificationsIfTipChanged(const uint256& old_tip) override
{
- if (!old_tip.IsNull()) {
- LOCK(::cs_main);
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
- if (old_tip == active.Tip()->GetBlockHash()) return;
- }
+ if (!old_tip.IsNull() && old_tip == WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip()->GetBlockHash())) return;
SyncWithValidationInterfaceQueue();
}
std::unique_ptr<Handler> handleRpc(const CRPCCommand& command) override
@@ -767,6 +766,13 @@ public:
notifications.transactionAddedToMempool(entry.GetSharedTx(), 0 /* mempool_sequence */);
}
}
+ bool hasAssumedValidChain() override
+ {
+ return chainman().IsSnapshotActive();
+ }
+
+ NodeContext* context() override { return &m_node; }
+ ChainstateManager& chainman() { return *Assert(m_node.chainman); }
NodeContext& m_node;
};
} // namespace
diff --git a/src/node/mempool_args.cpp b/src/node/mempool_args.cpp
new file mode 100644
index 0000000000..8c929e5e0d
--- /dev/null
+++ b/src/node/mempool_args.cpp
@@ -0,0 +1,100 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <node/mempool_args.h>
+
+#include <kernel/mempool_limits.h>
+#include <kernel/mempool_options.h>
+
+#include <chainparams.h>
+#include <consensus/amount.h>
+#include <logging.h>
+#include <policy/feerate.h>
+#include <policy/policy.h>
+#include <script/standard.h>
+#include <tinyformat.h>
+#include <util/error.h>
+#include <util/moneystr.h>
+#include <util/system.h>
+#include <util/translation.h>
+
+#include <chrono>
+#include <memory>
+
+using kernel::MemPoolLimits;
+using kernel::MemPoolOptions;
+
+namespace {
+void ApplyArgsManOptions(const ArgsManager& argsman, MemPoolLimits& mempool_limits)
+{
+ mempool_limits.ancestor_count = argsman.GetIntArg("-limitancestorcount", mempool_limits.ancestor_count);
+
+ if (auto vkb = argsman.GetIntArg("-limitancestorsize")) mempool_limits.ancestor_size_vbytes = *vkb * 1'000;
+
+ mempool_limits.descendant_count = argsman.GetIntArg("-limitdescendantcount", mempool_limits.descendant_count);
+
+ if (auto vkb = argsman.GetIntArg("-limitdescendantsize")) mempool_limits.descendant_size_vbytes = *vkb * 1'000;
+}
+}
+
+std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, MemPoolOptions& mempool_opts)
+{
+ mempool_opts.check_ratio = argsman.GetIntArg("-checkmempool", mempool_opts.check_ratio);
+
+ if (auto mb = argsman.GetIntArg("-maxmempool")) mempool_opts.max_size_bytes = *mb * 1'000'000;
+
+ if (auto hours = argsman.GetIntArg("-mempoolexpiry")) mempool_opts.expiry = std::chrono::hours{*hours};
+
+ // incremental relay fee sets the minimum feerate increase necessary for replacement in the mempool
+ // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
+ if (argsman.IsArgSet("-incrementalrelayfee")) {
+ if (std::optional<CAmount> inc_relay_fee = ParseMoney(argsman.GetArg("-incrementalrelayfee", ""))) {
+ mempool_opts.incremental_relay_feerate = CFeeRate{inc_relay_fee.value()};
+ } else {
+ return AmountErrMsg("incrementalrelayfee", argsman.GetArg("-incrementalrelayfee", ""));
+ }
+ }
+
+ if (argsman.IsArgSet("-minrelaytxfee")) {
+ if (std::optional<CAmount> min_relay_feerate = ParseMoney(argsman.GetArg("-minrelaytxfee", ""))) {
+ // High fee check is done afterward in CWallet::Create()
+ mempool_opts.min_relay_feerate = CFeeRate{min_relay_feerate.value()};
+ } else {
+ return AmountErrMsg("minrelaytxfee", argsman.GetArg("-minrelaytxfee", ""));
+ }
+ } else if (mempool_opts.incremental_relay_feerate > mempool_opts.min_relay_feerate) {
+ // Allow only setting incremental fee to control both
+ mempool_opts.min_relay_feerate = mempool_opts.incremental_relay_feerate;
+ LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n", mempool_opts.min_relay_feerate.ToString());
+ }
+
+ // Feerate used to define dust. Shouldn't be changed lightly as old
+ // implementations may inadvertently create non-standard transactions
+ if (argsman.IsArgSet("-dustrelayfee")) {
+ if (std::optional<CAmount> parsed = ParseMoney(argsman.GetArg("-dustrelayfee", ""))) {
+ mempool_opts.dust_relay_feerate = CFeeRate{parsed.value()};
+ } else {
+ return AmountErrMsg("dustrelayfee", argsman.GetArg("-dustrelayfee", ""));
+ }
+ }
+
+ mempool_opts.permit_bare_multisig = argsman.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
+
+ if (argsman.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER)) {
+ mempool_opts.max_datacarrier_bytes = argsman.GetIntArg("-datacarriersize", MAX_OP_RETURN_RELAY);
+ } else {
+ mempool_opts.max_datacarrier_bytes = std::nullopt;
+ }
+
+ mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
+ if (!chainparams.IsTestChain() && !mempool_opts.require_standard) {
+ return strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString());
+ }
+
+ mempool_opts.full_rbf = argsman.GetBoolArg("-mempoolfullrbf", mempool_opts.full_rbf);
+
+ ApplyArgsManOptions(argsman, mempool_opts.limits);
+
+ return std::nullopt;
+}
diff --git a/src/node/mempool_args.h b/src/node/mempool_args.h
new file mode 100644
index 0000000000..52d8b4f265
--- /dev/null
+++ b/src/node/mempool_args.h
@@ -0,0 +1,27 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_MEMPOOL_ARGS_H
+#define BITCOIN_NODE_MEMPOOL_ARGS_H
+
+#include <optional>
+
+class ArgsManager;
+class CChainParams;
+struct bilingual_str;
+namespace kernel {
+struct MemPoolOptions;
+};
+
+/**
+ * Overlay the options set in \p argsman on top of corresponding members in \p mempool_opts.
+ * Returns an error if one was encountered.
+ *
+ * @param[in] argsman The ArgsManager in which to check set options.
+ * @param[in,out] mempool_opts The MemPoolOptions to modify according to \p argsman.
+ */
+[[nodiscard]] std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, const CChainParams& chainparams, kernel::MemPoolOptions& mempool_opts);
+
+
+#endif // BITCOIN_NODE_MEMPOOL_ARGS_H
diff --git a/src/node/mempool_persist_args.cpp b/src/node/mempool_persist_args.cpp
new file mode 100644
index 0000000000..4e775869c6
--- /dev/null
+++ b/src/node/mempool_persist_args.cpp
@@ -0,0 +1,23 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <node/mempool_persist_args.h>
+
+#include <fs.h>
+#include <util/system.h>
+#include <validation.h>
+
+namespace node {
+
+bool ShouldPersistMempool(const ArgsManager& argsman)
+{
+ return argsman.GetBoolArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL);
+}
+
+fs::path MempoolPath(const ArgsManager& argsman)
+{
+ return argsman.GetDataDirNet() / "mempool.dat";
+}
+
+} // namespace node
diff --git a/src/node/mempool_persist_args.h b/src/node/mempool_persist_args.h
new file mode 100644
index 0000000000..f719ec62ab
--- /dev/null
+++ b/src/node/mempool_persist_args.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_MEMPOOL_PERSIST_ARGS_H
+#define BITCOIN_NODE_MEMPOOL_PERSIST_ARGS_H
+
+#include <fs.h>
+
+class ArgsManager;
+
+namespace node {
+
+/**
+ * Default for -persistmempool, indicating whether the node should attempt to
+ * automatically load the mempool on start and save to disk on shutdown
+ */
+static constexpr bool DEFAULT_PERSIST_MEMPOOL{true};
+
+bool ShouldPersistMempool(const ArgsManager& argsman);
+fs::path MempoolPath(const ArgsManager& argsman);
+
+} // namespace node
+
+#endif // BITCOIN_NODE_MEMPOOL_PERSIST_ARGS_H
diff --git a/src/node/miner.cpp b/src/node/miner.cpp
index 9db10feae4..b277188c1f 100644
--- a/src/node/miner.cpp
+++ b/src/node/miner.cpp
@@ -30,7 +30,7 @@ namespace node {
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
{
int64_t nOldTime = pblock->nTime;
- int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast() + 1, GetAdjustedTime());
+ int64_t nNewTime{std::max<int64_t>(pindexPrev->GetMedianTimePast() + 1, TicksSinceEpoch<std::chrono::seconds>(GetAdjustedTime()))};
if (nOldTime < nNewTime) {
pblock->nTime = nNewTime;
@@ -62,7 +62,7 @@ BlockAssembler::Options::Options()
nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
}
-BlockAssembler::BlockAssembler(CChainState& chainstate, const CTxMemPool* mempool, const Options& options)
+BlockAssembler::BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options)
: chainparams{chainstate.m_chainman.GetParams()},
m_mempool(mempool),
m_chainstate(chainstate)
@@ -87,7 +87,7 @@ static BlockAssembler::Options DefaultOptions()
return options;
}
-BlockAssembler::BlockAssembler(CChainState& chainstate, const CTxMemPool* mempool)
+BlockAssembler::BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool)
: BlockAssembler(chainstate, mempool, DefaultOptions()) {}
void BlockAssembler::resetBlock()
@@ -133,7 +133,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
pblock->nVersion = gArgs.GetIntArg("-blockversion", pblock->nVersion);
}
- pblock->nTime = GetAdjustedTime();
+ pblock->nTime = TicksSinceEpoch<std::chrono::seconds>(GetAdjustedTime());
m_lock_time_cutoff = pindexPrev->GetMedianTimePast();
int nPackagesSelected = 0;
diff --git a/src/node/miner.h b/src/node/miner.h
index 26454df3df..7269ce1186 100644
--- a/src/node/miner.h
+++ b/src/node/miner.h
@@ -148,7 +148,7 @@ private:
const CChainParams& chainparams;
const CTxMemPool* const m_mempool;
- CChainState& m_chainstate;
+ Chainstate& m_chainstate;
public:
struct Options {
@@ -157,8 +157,8 @@ public:
CFeeRate blockMinFeeRate;
};
- explicit BlockAssembler(CChainState& chainstate, const CTxMemPool* mempool);
- explicit BlockAssembler(CChainState& chainstate, const CTxMemPool* mempool, const Options& options);
+ explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool);
+ explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options);
/** Construct a new block template with coinbase to scriptPubKeyIn */
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
diff --git a/src/node/psbt.cpp b/src/node/psbt.cpp
index 5a932f435d..57162cd679 100644
--- a/src/node/psbt.cpp
+++ b/src/node/psbt.cpp
@@ -137,7 +137,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
if (success) {
CTransaction ctx = CTransaction(mtx);
- size_t size = GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS));
+ size_t size(GetVirtualTransactionSize(ctx, GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS), ::nBytesPerSigOp));
result.estimated_vsize = size;
// Estimate fee rate
CFeeRate feerate(fee, size);
diff --git a/src/node/utxo_snapshot.h b/src/node/utxo_snapshot.h
index 401d4baaeb..9dd6f06997 100644
--- a/src/node/utxo_snapshot.h
+++ b/src/node/utxo_snapshot.h
@@ -11,7 +11,7 @@
namespace node {
//! Metadata describing a serialized version of a UTXO set from which an
-//! assumeutxo CChainState can be constructed.
+//! assumeutxo Chainstate can be constructed.
class SnapshotMetadata
{
public:
diff --git a/src/node/validation_cache_args.cpp b/src/node/validation_cache_args.cpp
new file mode 100644
index 0000000000..5ea0a8ca0a
--- /dev/null
+++ b/src/node/validation_cache_args.cpp
@@ -0,0 +1,34 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <node/validation_cache_args.h>
+
+#include <kernel/validation_cache_sizes.h>
+
+#include <util/system.h>
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <optional>
+
+using kernel::ValidationCacheSizes;
+
+namespace node {
+void ApplyArgsManOptions(const ArgsManager& argsman, ValidationCacheSizes& cache_sizes)
+{
+ if (auto max_size = argsman.GetIntArg("-maxsigcachesize")) {
+ // 1. When supplied with a max_size of 0, both InitSignatureCache and
+ // InitScriptExecutionCache create the minimum possible cache (2
+ // elements). Therefore, we can use 0 as a floor here.
+ // 2. Multiply first, divide after to avoid integer truncation.
+ size_t clamped_size_each = std::max<int64_t>(*max_size, 0) * (1 << 20) / 2;
+ cache_sizes = {
+ .signature_cache_bytes = clamped_size_each,
+ .script_execution_cache_bytes = clamped_size_each,
+ };
+ }
+}
+} // namespace node
diff --git a/src/node/validation_cache_args.h b/src/node/validation_cache_args.h
new file mode 100644
index 0000000000..f447c13b49
--- /dev/null
+++ b/src/node/validation_cache_args.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_NODE_VALIDATION_CACHE_ARGS_H
+#define BITCOIN_NODE_VALIDATION_CACHE_ARGS_H
+
+class ArgsManager;
+namespace kernel {
+struct ValidationCacheSizes;
+};
+
+namespace node {
+void ApplyArgsManOptions(const ArgsManager& argsman, kernel::ValidationCacheSizes& cache_sizes);
+} // namespace node
+
+#endif // BITCOIN_NODE_VALIDATION_CACHE_ARGS_H
diff --git a/src/outputtype.cpp b/src/outputtype.cpp
index 19366295e6..9ab2902256 100644
--- a/src/outputtype.cpp
+++ b/src/outputtype.cpp
@@ -20,6 +20,7 @@ static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy";
static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit";
static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32";
static const std::string OUTPUT_TYPE_STRING_BECH32M = "bech32m";
+static const std::string OUTPUT_TYPE_STRING_UNKNOWN = "unknown";
std::optional<OutputType> ParseOutputType(const std::string& type)
{
@@ -31,6 +32,8 @@ std::optional<OutputType> ParseOutputType(const std::string& type)
return OutputType::BECH32;
} else if (type == OUTPUT_TYPE_STRING_BECH32M) {
return OutputType::BECH32M;
+ } else if (type == OUTPUT_TYPE_STRING_UNKNOWN) {
+ return OutputType::UNKNOWN;
}
return std::nullopt;
}
@@ -42,6 +45,7 @@ const std::string& FormatOutputType(OutputType type)
case OutputType::P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT;
case OutputType::BECH32: return OUTPUT_TYPE_STRING_BECH32;
case OutputType::BECH32M: return OUTPUT_TYPE_STRING_BECH32M;
+ case OutputType::UNKNOWN: return OUTPUT_TYPE_STRING_UNKNOWN;
} // no default case, so the compiler can warn about missing cases
assert(false);
}
@@ -61,7 +65,8 @@ CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type)
return witdest;
}
}
- case OutputType::BECH32M: {} // This function should never be used with BECH32M, so let it assert
+ case OutputType::BECH32M:
+ case OutputType::UNKNOWN: {} // This function should never be used with BECH32M or UNKNOWN, so let it assert
} // no default case, so the compiler can warn about missing cases
assert(false);
}
@@ -91,8 +96,6 @@ CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore,
case OutputType::BECH32: {
CTxDestination witdest = WitnessV0ScriptHash(script);
CScript witprog = GetScriptForDestination(witdest);
- // Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
- if (!IsSolvable(keystore, witprog)) return ScriptHash(script);
// Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
keystore.AddCScript(witprog);
if (type == OutputType::BECH32) {
@@ -101,7 +104,8 @@ CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore,
return ScriptHash(witprog);
}
}
- case OutputType::BECH32M: {} // This function should not be used for BECH32M, so let it assert
+ case OutputType::BECH32M:
+ case OutputType::UNKNOWN: {} // This function should not be used for BECH32M or UNKNOWN, so let it assert
} // no default case, so the compiler can warn about missing cases
assert(false);
}
diff --git a/src/outputtype.h b/src/outputtype.h
index 6b4e695760..c59262591b 100644
--- a/src/outputtype.h
+++ b/src/outputtype.h
@@ -19,6 +19,7 @@ enum class OutputType {
P2SH_SEGWIT,
BECH32,
BECH32M,
+ UNKNOWN,
};
static constexpr auto OUTPUT_TYPES = std::array{
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index b39632364f..2b940be07e 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -31,8 +31,6 @@
#include <stdexcept>
#include <utility>
-static const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat";
-
static constexpr double INF_FEERATE = 1e99;
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon)
@@ -163,13 +161,13 @@ public:
unsigned int GetMaxConfirms() const { return scale * confAvg.size(); }
/** Write state of estimation data to a file*/
- void Write(CAutoFile& fileout) const;
+ void Write(AutoFile& fileout) const;
/**
* Read saved state of estimation data from a file and replace all internal data structures and
* variables with this state.
*/
- void Read(CAutoFile& filein, int nFileVersion, size_t numBuckets);
+ void Read(AutoFile& filein, int nFileVersion, size_t numBuckets);
};
@@ -392,7 +390,7 @@ double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal,
return median;
}
-void TxConfirmStats::Write(CAutoFile& fileout) const
+void TxConfirmStats::Write(AutoFile& fileout) const
{
fileout << Using<EncodedDoubleFormatter>(decay);
fileout << scale;
@@ -402,7 +400,7 @@ void TxConfirmStats::Write(CAutoFile& fileout) const
fileout << Using<VectorFormatter<VectorFormatter<EncodedDoubleFormatter>>>(failAvg);
}
-void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets)
+void TxConfirmStats::Read(AutoFile& filein, int nFileVersion, size_t numBuckets)
{
// Read data file and do some very basic sanity checking
// buckets and bucketMap are not updated yet, so don't access them
@@ -529,8 +527,8 @@ bool CBlockPolicyEstimator::_removeTx(const uint256& hash, bool inBlock)
}
}
-CBlockPolicyEstimator::CBlockPolicyEstimator()
- : nBestSeenHeight(0), firstRecordedHeight(0), historicalFirst(0), historicalBest(0), trackedTxs(0), untrackedTxs(0)
+CBlockPolicyEstimator::CBlockPolicyEstimator(const fs::path& estimation_filepath)
+ : m_estimation_filepath{estimation_filepath}, nBestSeenHeight{0}, firstRecordedHeight{0}, historicalFirst{0}, historicalBest{0}, trackedTxs{0}, untrackedTxs{0}
{
static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
size_t bucketIndex = 0;
@@ -548,10 +546,9 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
longStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, LONG_BLOCK_PERIODS, LONG_DECAY, LONG_SCALE));
// If the fee estimation file is present, read recorded estimations
- fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
- CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
+ AutoFile est_file{fsbridge::fopen(m_estimation_filepath, "rb")};
if (est_file.IsNull() || !Read(est_file)) {
- LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", fs::PathToString(est_filepath));
+ LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", fs::PathToString(m_estimation_filepath));
}
}
@@ -907,14 +904,13 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
void CBlockPolicyEstimator::Flush() {
FlushUnconfirmed();
- fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
- CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
+ AutoFile est_file{fsbridge::fopen(m_estimation_filepath, "wb")};
if (est_file.IsNull() || !Write(est_file)) {
- LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", fs::PathToString(est_filepath));
+ LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", fs::PathToString(m_estimation_filepath));
}
}
-bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
+bool CBlockPolicyEstimator::Write(AutoFile& fileout) const
{
try {
LOCK(m_cs_fee_estimator);
@@ -939,7 +935,7 @@ bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
return true;
}
-bool CBlockPolicyEstimator::Read(CAutoFile& filein)
+bool CBlockPolicyEstimator::Read(AutoFile& filein)
{
try {
LOCK(m_cs_fee_estimator);
diff --git a/src/policy/fees.h b/src/policy/fees.h
index dea1e1d31b..e4628bf853 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -6,6 +6,7 @@
#define BITCOIN_POLICY_FEES_H
#include <consensus/amount.h>
+#include <fs.h>
#include <policy/feerate.h>
#include <random.h>
#include <sync.h>
@@ -19,7 +20,7 @@
#include <string>
#include <vector>
-class CAutoFile;
+class AutoFile;
class CTxMemPoolEntry;
class TxConfirmStats;
@@ -179,9 +180,10 @@ private:
*/
static constexpr double FEE_SPACING = 1.05;
+ const fs::path m_estimation_filepath;
public:
/** Create new BlockPolicyEstimator and initialize stats tracking classes with default values */
- CBlockPolicyEstimator();
+ CBlockPolicyEstimator(const fs::path& estimation_filepath);
~CBlockPolicyEstimator();
/** Process all the transactions that have been included in a block */
@@ -218,11 +220,11 @@ public:
EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator);
/** Write estimation data to a file */
- bool Write(CAutoFile& fileout) const
+ bool Write(AutoFile& fileout) const
EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator);
/** Read estimation data from a file */
- bool Read(CAutoFile& filein)
+ bool Read(AutoFile& filein)
EXCLUSIVE_LOCKS_REQUIRED(!m_cs_fee_estimator);
/** Empty mempool transactions on shutdown to record failure to confirm for txs still in mempool */
diff --git a/src/policy/fees_args.cpp b/src/policy/fees_args.cpp
new file mode 100644
index 0000000000..a3531153b5
--- /dev/null
+++ b/src/policy/fees_args.cpp
@@ -0,0 +1,12 @@
+#include <policy/fees_args.h>
+
+#include <util/system.h>
+
+namespace {
+const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat";
+} // namespace
+
+fs::path FeeestPath(const ArgsManager& argsman)
+{
+ return argsman.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
+}
diff --git a/src/policy/fees_args.h b/src/policy/fees_args.h
new file mode 100644
index 0000000000..6b65ce0aa9
--- /dev/null
+++ b/src/policy/fees_args.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_POLICY_FEES_ARGS_H
+#define BITCOIN_POLICY_FEES_ARGS_H
+
+#include <fs.h>
+
+class ArgsManager;
+
+/** @return The fee estimates data file path. */
+fs::path FeeestPath(const ArgsManager& argsman);
+
+#endif // BITCOIN_POLICY_FEES_ARGS_H
diff --git a/src/policy/packages.h b/src/policy/packages.h
index 564ff50d29..36c70e9e66 100644
--- a/src/policy/packages.h
+++ b/src/policy/packages.h
@@ -25,8 +25,8 @@ static_assert(MAX_PACKAGE_SIZE * WITNESS_SCALE_FACTOR * 1000 >= MAX_STANDARD_TX_
// defaults reflect this constraint.
static_assert(DEFAULT_DESCENDANT_LIMIT >= MAX_PACKAGE_COUNT);
static_assert(DEFAULT_ANCESTOR_LIMIT >= MAX_PACKAGE_COUNT);
-static_assert(DEFAULT_ANCESTOR_SIZE_LIMIT >= MAX_PACKAGE_SIZE);
-static_assert(DEFAULT_DESCENDANT_SIZE_LIMIT >= MAX_PACKAGE_SIZE);
+static_assert(DEFAULT_ANCESTOR_SIZE_LIMIT_KVB >= MAX_PACKAGE_SIZE);
+static_assert(DEFAULT_DESCENDANT_SIZE_LIMIT_KVB >= MAX_PACKAGE_SIZE);
/** A "reason" why a package was invalid. It may be that one or more of the included
* transactions is invalid or the package itself violates our rules.
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index f6452266b7..5086542865 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -67,7 +67,7 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
}
-bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
+bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType)
{
std::vector<std::vector<unsigned char> > vSolutions;
whichType = Solver(scriptPubKey, vSolutions);
@@ -82,15 +82,16 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
return false;
if (m < 1 || m > n)
return false;
- } else if (whichType == TxoutType::NULL_DATA &&
- (!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
- return false;
+ } else if (whichType == TxoutType::NULL_DATA) {
+ if (!max_datacarrier_bytes || scriptPubKey.size() > *max_datacarrier_bytes) {
+ return false;
+ }
}
return true;
}
-bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
+bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
{
if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version";
@@ -130,7 +131,7 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR
unsigned int nDataOut = 0;
TxoutType whichType;
for (const CTxOut& txout : tx.vout) {
- if (!::IsStandard(txout.scriptPubKey, whichType)) {
+ if (!::IsStandard(txout.scriptPubKey, max_datacarrier_bytes, whichType)) {
reason = "scriptpubkey";
return false;
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index cd46652efc..29764ea2d9 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -31,9 +31,7 @@ static constexpr unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE{82};
static constexpr unsigned int MAX_P2SH_SIGOPS{15};
/** The maximum number of sigops we're willing to relay/mine in a single tx */
static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5};
-/** Default for -maxmempool, maximum megabytes of mempool memory usage */
-static constexpr unsigned int DEFAULT_MAX_MEMPOOL_SIZE{300};
-/** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or BIP 125 replacement **/
+/** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/
static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000};
/** Default for -bytespersigop */
static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20};
@@ -49,8 +47,8 @@ static constexpr unsigned int MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE{80};
static constexpr unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE{3600};
/** The maximum size of a standard ScriptSig */
static constexpr unsigned int MAX_STANDARD_SCRIPTSIG_SIZE{1650};
-/** Min feerate for defining dust. Historically this has been based on the
- * minRelayTxFee, however changing the dust limit changes which transactions are
+/** Min feerate for defining dust.
+ * Changing the dust limit changes which transactions are
* standard and should be done with care and ideally rarely. It makes sense to
* only increase the dust limit after prior releases were already not creating
* outputs below the new threshold */
@@ -60,11 +58,11 @@ static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE{1000};
/** Default for -limitancestorcount, max number of in-mempool ancestors */
static constexpr unsigned int DEFAULT_ANCESTOR_LIMIT{25};
/** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */
-static constexpr unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT{101};
+static constexpr unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT_KVB{101};
/** Default for -limitdescendantcount, max number of in-mempool descendants */
static constexpr unsigned int DEFAULT_DESCENDANT_LIMIT{25};
/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */
-static constexpr unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT{101};
+static constexpr unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT_KVB{101};
/**
* An extra transaction can be added to a package, as long as it only has one
* ancestor and is no larger than this. Not really any reason to make this
@@ -101,14 +99,13 @@ static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS{MANDATORY_SCRIPT_VERI
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS{STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS};
/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
-static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS{LOCKTIME_VERIFY_SEQUENCE |
- LOCKTIME_MEDIAN_TIME_PAST};
+static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS{LOCKTIME_VERIFY_SEQUENCE};
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
-bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType);
+bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_datacarrier_bytes, TxoutType& whichType);
// Changing the default transaction version requires a two step process: first
@@ -120,7 +117,7 @@ static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{2};
* Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
*/
-bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
+bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
/**
* Check for standard transaction types
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index e25f5c7c5b..6098caced9 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -65,15 +65,15 @@ std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx,
uint64_t nConflictingCount = 0;
for (const auto& mi : iters_conflicting) {
nConflictingCount += mi->GetCountWithDescendants();
- // BIP125 Rule #5: don't consider replacing more than MAX_BIP125_REPLACEMENT_CANDIDATES
+ // Rule #5: don't consider replacing more than MAX_REPLACEMENT_CANDIDATES
// entries from the mempool. This potentially overestimates the number of actual
// descendants (i.e. if multiple conflicts share a descendant, it will be counted multiple
// times), but we just want to be conservative to avoid doing too much work.
- if (nConflictingCount > MAX_BIP125_REPLACEMENT_CANDIDATES) {
+ if (nConflictingCount > MAX_REPLACEMENT_CANDIDATES) {
return strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
txid.ToString(),
nConflictingCount,
- MAX_BIP125_REPLACEMENT_CANDIDATES);
+ MAX_REPLACEMENT_CANDIDATES);
}
}
// Calculate the set of all transactions that would have to be evicted.
@@ -96,7 +96,7 @@ std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx,
}
for (unsigned int j = 0; j < tx.vin.size(); j++) {
- // BIP125 Rule #2: We don't want to accept replacements that require low feerate junk to be
+ // Rule #2: We don't want to accept replacements that require low feerate junk to be
// mined first. Ideally we'd keep track of the ancestor feerates and make the decision
// based on that, but for now requiring all new inputs to be confirmed works.
//
@@ -162,7 +162,7 @@ std::optional<std::string> PaysForRBF(CAmount original_fees,
CFeeRate relay_fee,
const uint256& txid)
{
- // BIP125 Rule #3: The replacement fees must be greater than or equal to fees of the
+ // Rule #3: The replacement fees must be greater than or equal to fees of the
// transactions it replaces, otherwise the bandwidth used by those conflicting transactions
// would not be paid for.
if (replacement_fees < original_fees) {
@@ -170,7 +170,7 @@ std::optional<std::string> PaysForRBF(CAmount original_fees,
txid.ToString(), FormatMoney(replacement_fees), FormatMoney(original_fees));
}
- // BIP125 Rule #4: The new transaction must pay for its own bandwidth. Otherwise, we have a DoS
+ // Rule #4: The new transaction must pay for its own bandwidth. Otherwise, we have a DoS
// vector where attackers can cause a transaction to be replaced (and relayed) repeatedly by
// increasing the fee by tiny amounts.
CAmount additional_fees = replacement_fees - original_fees;
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index 07f68c8fd4..28c4e4bf9b 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -19,9 +19,9 @@
class CFeeRate;
class uint256;
-/** Maximum number of transactions that can be replaced by BIP125 RBF (Rule #5). This includes all
+/** Maximum number of transactions that can be replaced by RBF (Rule #5). This includes all
* mempool conflicts and their descendants. */
-static constexpr uint32_t MAX_BIP125_REPLACEMENT_CANDIDATES{100};
+static constexpr uint32_t MAX_REPLACEMENT_CANDIDATES{100};
/** The rbf state of unconfirmed transactions */
enum class RBFTransactionState {
@@ -47,24 +47,25 @@ enum class RBFTransactionState {
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx);
-/** Get all descendants of iters_conflicting. Also enforce BIP125 Rule #5, "The number of original
- * transactions to be replaced and their descendant transactions which will be evicted from the
- * mempool must not exceed a total of 100 transactions." Quit as early as possible. There cannot be
- * more than MAX_BIP125_REPLACEMENT_CANDIDATES potential entries.
+/** Get all descendants of iters_conflicting. Checks that there are no more than
+ * MAX_REPLACEMENT_CANDIDATES potential entries. May overestimate if the entries in
+ * iters_conflicting have overlapping descendants.
* @param[in] iters_conflicting The set of iterators to mempool entries.
* @param[out] all_conflicts Populated with all the mempool entries that would be replaced,
- * which includes descendants of iters_conflicting. Not cleared at
- * the start; any existing mempool entries will remain in the set.
- * @returns an error message if Rule #5 is broken, otherwise a std::nullopt.
+ * which includes iters_conflicting and all entries' descendants.
+ * Not cleared at the start; any existing mempool entries will
+ * remain in the set.
+ * @returns an error message if MAX_REPLACEMENT_CANDIDATES may be exceeded, otherwise a std::nullopt.
*/
std::optional<std::string> GetEntriesForConflicts(const CTransaction& tx, CTxMemPool& pool,
const CTxMemPool::setEntries& iters_conflicting,
CTxMemPool::setEntries& all_conflicts)
EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
-/** BIP125 Rule #2: "The replacement transaction may only include an unconfirmed input if that input
- * was included in one of the original transactions."
- * @returns error message if Rule #2 is broken, otherwise std::nullopt. */
+/** The replacement transaction may only include an unconfirmed input if that input was included in
+ * one of the original transactions.
+ * @returns error message if tx spends unconfirmed inputs not also spent by iters_conflicting,
+ * otherwise std::nullopt. */
std::optional<std::string> HasNoNewUnconfirmed(const CTransaction& tx, const CTxMemPool& pool,
const CTxMemPool::setEntries& iters_conflicting)
EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
@@ -90,9 +91,8 @@ std::optional<std::string> EntriesAndTxidsDisjoint(const CTxMemPool::setEntries&
std::optional<std::string> PaysMoreThanConflicts(const CTxMemPool::setEntries& iters_conflicting,
CFeeRate replacement_feerate, const uint256& txid);
-/** Enforce BIP125 Rule #3 "The replacement transaction pays an absolute fee of at least the sum
- * paid by the original transactions." Enforce BIP125 Rule #4 "The replacement transaction must also
- * pay for its own bandwidth at or above the rate set by the node's minimum relay fee setting."
+/** The replacement transaction must pay more fees than the original transactions. The additional
+ * fees must pay for the replacement's bandwidth at or above the incremental relay feerate.
* @param[in] original_fees Total modified fees of original transaction(s).
* @param[in] replacement_fees Total modified fees of replacement transaction(s).
* @param[in] replacement_vsize Total virtual size of replacement transaction(s).
diff --git a/src/policy/settings.cpp b/src/policy/settings.cpp
index 0b67d274ce..39e00f1111 100644
--- a/src/policy/settings.cpp
+++ b/src/policy/settings.cpp
@@ -5,11 +5,6 @@
#include <policy/settings.h>
-#include <policy/feerate.h>
#include <policy/policy.h>
-bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
-CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
-CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
-CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
diff --git a/src/policy/settings.h b/src/policy/settings.h
index 2311d01fe8..f0d6f779ae 100644
--- a/src/policy/settings.h
+++ b/src/policy/settings.h
@@ -6,35 +6,6 @@
#ifndef BITCOIN_POLICY_SETTINGS_H
#define BITCOIN_POLICY_SETTINGS_H
-#include <policy/feerate.h>
-#include <policy/policy.h>
-
-#include <cstdint>
-#include <string>
-
-class CTransaction;
-
-// Policy settings which are configurable at runtime.
-extern CFeeRate incrementalRelayFee;
-extern CFeeRate dustRelayFee;
-/** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */
-extern CFeeRate minRelayTxFee;
extern unsigned int nBytesPerSigOp;
-extern bool fIsBareMultisigStd;
-
-static inline bool IsStandardTx(const CTransaction& tx, std::string& reason)
-{
- return IsStandardTx(tx, ::fIsBareMultisigStd, ::dustRelayFee, reason);
-}
-
-static inline int64_t GetVirtualTransactionSize(int64_t weight, int64_t sigop_cost)
-{
- return GetVirtualTransactionSize(weight, sigop_cost, ::nBytesPerSigOp);
-}
-
-static inline int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t sigop_cost)
-{
- return GetVirtualTransactionSize(tx, sigop_cost, ::nBytesPerSigOp);
-}
#endif // BITCOIN_POLICY_SETTINGS_H
diff --git a/src/pow.cpp b/src/pow.cpp
index 1414d37564..c0449cac74 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -71,6 +71,57 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
return bnNew.GetCompact();
}
+// Check that on difficulty adjustments, the new difficulty does not increase
+// or decrease beyond the permitted limits.
+bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits)
+{
+ if (params.fPowAllowMinDifficultyBlocks) return true;
+
+ if (height % params.DifficultyAdjustmentInterval() == 0) {
+ int64_t smallest_timespan = params.nPowTargetTimespan/4;
+ int64_t largest_timespan = params.nPowTargetTimespan*4;
+
+ const arith_uint256 pow_limit = UintToArith256(params.powLimit);
+ arith_uint256 observed_new_target;
+ observed_new_target.SetCompact(new_nbits);
+
+ // Calculate the largest difficulty value possible:
+ arith_uint256 largest_difficulty_target;
+ largest_difficulty_target.SetCompact(old_nbits);
+ largest_difficulty_target *= largest_timespan;
+ largest_difficulty_target /= params.nPowTargetTimespan;
+
+ if (largest_difficulty_target > pow_limit) {
+ largest_difficulty_target = pow_limit;
+ }
+
+ // Round and then compare this new calculated value to what is
+ // observed.
+ arith_uint256 maximum_new_target;
+ maximum_new_target.SetCompact(largest_difficulty_target.GetCompact());
+ if (maximum_new_target < observed_new_target) return false;
+
+ // Calculate the smallest difficulty value possible:
+ arith_uint256 smallest_difficulty_target;
+ smallest_difficulty_target.SetCompact(old_nbits);
+ smallest_difficulty_target *= smallest_timespan;
+ smallest_difficulty_target /= params.nPowTargetTimespan;
+
+ if (smallest_difficulty_target > pow_limit) {
+ smallest_difficulty_target = pow_limit;
+ }
+
+ // Round and then compare this new calculated value to what is
+ // observed.
+ arith_uint256 minimum_new_target;
+ minimum_new_target.SetCompact(smallest_difficulty_target.GetCompact());
+ if (minimum_new_target > observed_new_target) return false;
+ } else if (old_nbits != new_nbits) {
+ return false;
+ }
+ return true;
+}
+
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
bool fNegative;
diff --git a/src/pow.h b/src/pow.h
index 1d802cd01e..44b9d673ef 100644
--- a/src/pow.h
+++ b/src/pow.h
@@ -20,4 +20,18 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
+/**
+ * Return false if the proof-of-work requirement specified by new_nbits at a
+ * given height is not possible, given the proof-of-work on the prior block as
+ * specified by old_nbits.
+ *
+ * This function only checks that the new value is within a factor of 4 of the
+ * old value for blocks at the difficulty adjustment interval, and otherwise
+ * requires the values to be the same.
+ *
+ * Always returns true on networks where min difficulty blocks are allowed,
+ * such as regtest/testnet.
+ */
+bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t height, uint32_t old_nbits, uint32_t new_nbits);
+
#endif // BITCOIN_POW_H
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 2d10853607..2e26e6c426 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -9,6 +9,7 @@
#include <primitives/transaction.h>
#include <serialize.h>
#include <uint256.h>
+#include <util/time.h>
/** Nodes collect new transactions into a block, hash them into a hash tree,
* and scan through nonce values to make the block's hash satisfy proof-of-work
@@ -52,6 +53,11 @@ public:
uint256 GetHash() const;
+ NodeSeconds Time() const
+ {
+ return NodeSeconds{std::chrono::seconds{nTime}};
+ }
+
int64_t GetBlockTime() const
{
return (int64_t)nTime;
@@ -117,7 +123,7 @@ struct CBlockLocator
CBlockLocator() {}
- explicit CBlockLocator(const std::vector<uint256>& vHaveIn) : vHave(vHaveIn) {}
+ explicit CBlockLocator(std::vector<uint256>&& have) : vHave(std::move(have)) {}
SERIALIZE_METHODS(CBlockLocator, obj)
{
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index f7f6ae4480..ec48194ee9 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -7,10 +7,15 @@
#include <consensus/amount.h>
#include <hash.h>
+#include <script/script.h>
+#include <serialize.h>
#include <tinyformat.h>
+#include <uint256.h>
#include <util/strencodings.h>
+#include <version.h>
-#include <assert.h>
+#include <cassert>
+#include <stdexcept>
std::string COutPoint::ToString() const
{
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index fb98fb6868..f496ea022e 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -6,13 +6,21 @@
#ifndef BITCOIN_PRIMITIVES_TRANSACTION_H
#define BITCOIN_PRIMITIVES_TRANSACTION_H
-#include <stdint.h>
#include <consensus/amount.h>
+#include <prevector.h>
#include <script/script.h>
#include <serialize.h>
#include <uint256.h>
+#include <cstddef>
+#include <cstdint>
+#include <ios>
+#include <limits>
+#include <memory>
+#include <string>
#include <tuple>
+#include <utility>
+#include <vector>
/**
* A flag that is ORed into the protocol version to designate that a transaction
@@ -303,7 +311,7 @@ private:
public:
/** Convert a CMutableTransaction into a CTransaction. */
explicit CTransaction(const CMutableTransaction& tx);
- CTransaction(CMutableTransaction&& tx);
+ explicit CTransaction(CMutableTransaction&& tx);
template <typename Stream>
inline void Serialize(Stream& s) const {
@@ -368,7 +376,7 @@ struct CMutableTransaction
int32_t nVersion;
uint32_t nLockTime;
- CMutableTransaction();
+ explicit CMutableTransaction();
explicit CMutableTransaction(const CTransaction& tx);
template <typename Stream>
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 139405170b..bdd1cc2aff 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -199,12 +199,7 @@ static std::string serviceFlagToStr(size_t bit)
// Not using default, so we get warned when a case is missing
}
- std::ostringstream stream;
- stream.imbue(std::locale::classic());
- stream << "UNKNOWN[";
- stream << "2^" << bit;
- stream << "]";
- return stream.str();
+ return strprintf("UNKNOWN[2^%u]", bit);
}
std::vector<std::string> serviceFlagsToStr(uint64_t flags)
diff --git a/src/protocol.h b/src/protocol.h
index da2d24aff3..b85dc0d820 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -11,6 +11,7 @@
#include <serialize.h>
#include <streams.h>
#include <uint256.h>
+#include <util/time.h>
#include <cstdint>
#include <limits>
@@ -352,7 +353,7 @@ static inline bool MayHaveUsefulAddressDB(ServiceFlags services)
/** A CService with information about it as peer */
class CAddress : public CService
{
- static constexpr uint32_t TIME_INIT{100000000};
+ static constexpr std::chrono::seconds TIME_INIT{100000000};
/** Historically, CAddress disk serialization stored the CLIENT_VERSION, optionally OR'ed with
* the ADDRV2_FORMAT flag to indicate V2 serialization. The first field has since been
@@ -382,7 +383,7 @@ class CAddress : public CService
public:
CAddress() : CService{} {};
CAddress(CService ipIn, ServiceFlags nServicesIn) : CService{ipIn}, nServices{nServicesIn} {};
- CAddress(CService ipIn, ServiceFlags nServicesIn, uint32_t nTimeIn) : CService{ipIn}, nTime{nTimeIn}, nServices{nServicesIn} {};
+ CAddress(CService ipIn, ServiceFlags nServicesIn, NodeSeconds time) : CService{ipIn}, nTime{time}, nServices{nServicesIn} {};
SERIALIZE_METHODS(CAddress, obj)
{
@@ -415,7 +416,7 @@ public:
use_v2 = s.GetVersion() & ADDRV2_FORMAT;
}
- READWRITE(obj.nTime);
+ READWRITE(Using<LossyChronoFormatter<uint32_t>>(obj.nTime));
// nServices is serialized as CompactSize in V2; as uint64_t in V1.
if (use_v2) {
uint64_t services_tmp;
@@ -430,8 +431,8 @@ public:
SerReadWriteMany(os, ser_action, ReadWriteAsHelper<CService>(obj));
}
- //! Always included in serialization.
- uint32_t nTime{TIME_INIT};
+ //! Always included in serialization. The behavior is unspecified if the value is not representable as uint32_t.
+ NodeSeconds nTime{TIME_INIT};
//! Serialized as uint64_t in V1, and as CompactSize in V2.
ServiceFlags nServices{NODE_NONE};
diff --git a/src/psbt.cpp b/src/psbt.cpp
index c1c8a385cc..cbf2f88788 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -113,6 +113,24 @@ void PSBTInput::FillSignatureData(SignatureData& sigdata) const
for (const auto& key_pair : hd_keypaths) {
sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
}
+ if (!m_tap_key_sig.empty()) {
+ sigdata.taproot_key_path_sig = m_tap_key_sig;
+ }
+ for (const auto& [pubkey_leaf, sig] : m_tap_script_sigs) {
+ sigdata.taproot_script_sigs.emplace(pubkey_leaf, sig);
+ }
+ if (!m_tap_internal_key.IsNull()) {
+ sigdata.tr_spenddata.internal_key = m_tap_internal_key;
+ }
+ if (!m_tap_merkle_root.IsNull()) {
+ sigdata.tr_spenddata.merkle_root = m_tap_merkle_root;
+ }
+ for (const auto& [leaf_script, control_block] : m_tap_scripts) {
+ sigdata.tr_spenddata.scripts.emplace(leaf_script, control_block);
+ }
+ for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {
+ sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);
+ }
}
void PSBTInput::FromSignatureData(const SignatureData& sigdata)
@@ -142,13 +160,30 @@ void PSBTInput::FromSignatureData(const SignatureData& sigdata)
for (const auto& entry : sigdata.misc_pubkeys) {
hd_keypaths.emplace(entry.second);
}
+ if (!sigdata.taproot_key_path_sig.empty()) {
+ m_tap_key_sig = sigdata.taproot_key_path_sig;
+ }
+ for (const auto& [pubkey_leaf, sig] : sigdata.taproot_script_sigs) {
+ m_tap_script_sigs.emplace(pubkey_leaf, sig);
+ }
+ if (!sigdata.tr_spenddata.internal_key.IsNull()) {
+ m_tap_internal_key = sigdata.tr_spenddata.internal_key;
+ }
+ if (!sigdata.tr_spenddata.merkle_root.IsNull()) {
+ m_tap_merkle_root = sigdata.tr_spenddata.merkle_root;
+ }
+ for (const auto& [leaf_script, control_block] : sigdata.tr_spenddata.scripts) {
+ m_tap_scripts.emplace(leaf_script, control_block);
+ }
+ for (const auto& [pubkey, leaf_origin] : sigdata.taproot_misc_pubkeys) {
+ m_tap_bip32_paths.emplace(pubkey, leaf_origin);
+ }
}
void PSBTInput::Merge(const PSBTInput& input)
{
if (!non_witness_utxo && input.non_witness_utxo) non_witness_utxo = input.non_witness_utxo;
if (witness_utxo.IsNull() && !input.witness_utxo.IsNull()) {
- // TODO: For segwit v1, we will want to clear out the non-witness utxo when setting a witness one. For v0 and non-segwit, this is not safe
witness_utxo = input.witness_utxo;
}
@@ -159,11 +194,17 @@ void PSBTInput::Merge(const PSBTInput& input)
hash256_preimages.insert(input.hash256_preimages.begin(), input.hash256_preimages.end());
hd_keypaths.insert(input.hd_keypaths.begin(), input.hd_keypaths.end());
unknown.insert(input.unknown.begin(), input.unknown.end());
+ m_tap_script_sigs.insert(input.m_tap_script_sigs.begin(), input.m_tap_script_sigs.end());
+ m_tap_scripts.insert(input.m_tap_scripts.begin(), input.m_tap_scripts.end());
+ m_tap_bip32_paths.insert(input.m_tap_bip32_paths.begin(), input.m_tap_bip32_paths.end());
if (redeem_script.empty() && !input.redeem_script.empty()) redeem_script = input.redeem_script;
if (witness_script.empty() && !input.witness_script.empty()) witness_script = input.witness_script;
if (final_script_sig.empty() && !input.final_script_sig.empty()) final_script_sig = input.final_script_sig;
if (final_script_witness.IsNull() && !input.final_script_witness.IsNull()) final_script_witness = input.final_script_witness;
+ if (m_tap_key_sig.empty() && !input.m_tap_key_sig.empty()) m_tap_key_sig = input.m_tap_key_sig;
+ if (m_tap_internal_key.IsNull() && !input.m_tap_internal_key.IsNull()) m_tap_internal_key = input.m_tap_internal_key;
+ if (m_tap_merkle_root.IsNull() && !input.m_tap_merkle_root.IsNull()) m_tap_merkle_root = input.m_tap_merkle_root;
}
void PSBTOutput::FillSignatureData(SignatureData& sigdata) const
@@ -177,6 +218,21 @@ void PSBTOutput::FillSignatureData(SignatureData& sigdata) const
for (const auto& key_pair : hd_keypaths) {
sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
}
+ if (!m_tap_tree.empty() && m_tap_internal_key.IsFullyValid()) {
+ TaprootBuilder builder;
+ for (const auto& [depth, leaf_ver, script] : m_tap_tree) {
+ builder.Add((int)depth, script, (int)leaf_ver, /*track=*/true);
+ }
+ assert(builder.IsComplete());
+ builder.Finalize(m_tap_internal_key);
+ TaprootSpendData spenddata = builder.GetSpendData();
+
+ sigdata.tr_spenddata.internal_key = m_tap_internal_key;
+ sigdata.tr_spenddata.Merge(spenddata);
+ }
+ for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {
+ sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);
+ }
}
void PSBTOutput::FromSignatureData(const SignatureData& sigdata)
@@ -190,6 +246,15 @@ void PSBTOutput::FromSignatureData(const SignatureData& sigdata)
for (const auto& entry : sigdata.misc_pubkeys) {
hd_keypaths.emplace(entry.second);
}
+ if (!sigdata.tr_spenddata.internal_key.IsNull()) {
+ m_tap_internal_key = sigdata.tr_spenddata.internal_key;
+ }
+ if (sigdata.tr_builder.has_value() && sigdata.tr_builder->HasScripts()) {
+ m_tap_tree = sigdata.tr_builder->GetTreeTuples();
+ }
+ for (const auto& [pubkey, leaf_origin] : sigdata.taproot_misc_pubkeys) {
+ m_tap_bip32_paths.emplace(pubkey, leaf_origin);
+ }
}
bool PSBTOutput::IsNull() const
@@ -201,9 +266,12 @@ void PSBTOutput::Merge(const PSBTOutput& output)
{
hd_keypaths.insert(output.hd_keypaths.begin(), output.hd_keypaths.end());
unknown.insert(output.unknown.begin(), output.unknown.end());
+ m_tap_bip32_paths.insert(output.m_tap_bip32_paths.begin(), output.m_tap_bip32_paths.end());
if (redeem_script.empty() && !output.redeem_script.empty()) redeem_script = output.redeem_script;
if (witness_script.empty() && !output.witness_script.empty()) witness_script = output.witness_script;
+ if (m_tap_internal_key.IsNull() && !output.m_tap_internal_key.IsNull()) m_tap_internal_key = output.m_tap_internal_key;
+ if (m_tap_tree.empty() && !output.m_tap_tree.empty()) m_tap_tree = output.m_tap_tree;
}
bool PSBTInputSigned(const PSBTInput& input)
{
@@ -313,10 +381,11 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
input.FromSignatureData(sigdata);
// If we have a witness signature, put a witness UTXO.
- // TODO: For segwit v1, we should remove the non_witness_utxo
if (sigdata.witness) {
input.witness_utxo = utxo;
- // input.non_witness_utxo = nullptr;
+ // We can remove the non_witness_utxo if and only if there are no non-segwit or segwit v0
+ // inputs in this transaction. Since this requires inspecting the entire transaction, this
+ // is something for the caller to deal with (i.e. FillPSBT).
}
// Fill in the missing info
diff --git a/src/psbt.h b/src/psbt.h
index 4a6d41076f..ddcdb8c68d 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -40,12 +40,21 @@ static constexpr uint8_t PSBT_IN_RIPEMD160 = 0x0A;
static constexpr uint8_t PSBT_IN_SHA256 = 0x0B;
static constexpr uint8_t PSBT_IN_HASH160 = 0x0C;
static constexpr uint8_t PSBT_IN_HASH256 = 0x0D;
+static constexpr uint8_t PSBT_IN_TAP_KEY_SIG = 0x13;
+static constexpr uint8_t PSBT_IN_TAP_SCRIPT_SIG = 0x14;
+static constexpr uint8_t PSBT_IN_TAP_LEAF_SCRIPT = 0x15;
+static constexpr uint8_t PSBT_IN_TAP_BIP32_DERIVATION = 0x16;
+static constexpr uint8_t PSBT_IN_TAP_INTERNAL_KEY = 0x17;
+static constexpr uint8_t PSBT_IN_TAP_MERKLE_ROOT = 0x18;
static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC;
// Output types
static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00;
static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01;
static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
+static constexpr uint8_t PSBT_OUT_TAP_INTERNAL_KEY = 0x05;
+static constexpr uint8_t PSBT_OUT_TAP_TREE = 0x06;
+static constexpr uint8_t PSBT_OUT_TAP_BIP32_DERIVATION = 0x07;
static constexpr uint8_t PSBT_OUT_PROPRIETARY = 0xFC;
// The separator is 0x00. Reading this in means that the unserializer can interpret it
@@ -97,22 +106,30 @@ void UnserializeFromVector(Stream& s, X&... args)
}
}
-// Deserialize an individual HD keypath to a stream
+// Deserialize bytes of given length from the stream as a KeyOriginInfo
template<typename Stream>
-void DeserializeHDKeypath(Stream& s, KeyOriginInfo& hd_keypath)
+KeyOriginInfo DeserializeKeyOrigin(Stream& s, uint64_t length)
{
// Read in key path
- uint64_t value_len = ReadCompactSize(s);
- if (value_len % 4 || value_len == 0) {
+ if (length % 4 || length == 0) {
throw std::ios_base::failure("Invalid length for HD key path");
}
+ KeyOriginInfo hd_keypath;
s >> hd_keypath.fingerprint;
- for (unsigned int i = 4; i < value_len; i += sizeof(uint32_t)) {
+ for (unsigned int i = 4; i < length; i += sizeof(uint32_t)) {
uint32_t index;
s >> index;
hd_keypath.path.push_back(index);
}
+ return hd_keypath;
+}
+
+// Deserialize a length prefixed KeyOriginInfo from a stream
+template<typename Stream>
+void DeserializeHDKeypath(Stream& s, KeyOriginInfo& hd_keypath)
+{
+ hd_keypath = DeserializeKeyOrigin(s, ReadCompactSize(s));
}
// Deserialize HD keypaths into a map
@@ -139,17 +156,24 @@ void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std
hd_keypaths.emplace(pubkey, std::move(keypath));
}
-// Serialize an individual HD keypath to a stream
+// Serialize a KeyOriginInfo to a stream
template<typename Stream>
-void SerializeHDKeypath(Stream& s, KeyOriginInfo hd_keypath)
+void SerializeKeyOrigin(Stream& s, KeyOriginInfo hd_keypath)
{
- WriteCompactSize(s, (hd_keypath.path.size() + 1) * sizeof(uint32_t));
s << hd_keypath.fingerprint;
for (const auto& path : hd_keypath.path) {
s << path;
}
}
+// Serialize a length prefixed KeyOriginInfo to a stream
+template<typename Stream>
+void SerializeHDKeypath(Stream& s, KeyOriginInfo hd_keypath)
+{
+ WriteCompactSize(s, (hd_keypath.path.size() + 1) * sizeof(uint32_t));
+ SerializeKeyOrigin(s, hd_keypath);
+}
+
// Serialize HD keypaths to a stream from a map
template<typename Stream>
void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, KeyOriginInfo>& hd_keypaths, CompactSizeWriter type)
@@ -178,6 +202,15 @@ struct PSBTInput
std::map<uint256, std::vector<unsigned char>> sha256_preimages;
std::map<uint160, std::vector<unsigned char>> hash160_preimages;
std::map<uint256, std::vector<unsigned char>> hash256_preimages;
+
+ // Taproot fields
+ std::vector<unsigned char> m_tap_key_sig;
+ std::map<std::pair<XOnlyPubKey, uint256>, std::vector<unsigned char>> m_tap_script_sigs;
+ std::map<std::pair<CScript, int>, std::set<std::vector<unsigned char>, ShortestVectorFirstComparator>> m_tap_scripts;
+ std::map<XOnlyPubKey, std::pair<std::set<uint256>, KeyOriginInfo>> m_tap_bip32_paths;
+ XOnlyPubKey m_tap_internal_key;
+ uint256 m_tap_merkle_root;
+
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
std::set<PSBTProprietary> m_proprietary;
std::optional<int> sighash_type;
@@ -252,6 +285,53 @@ struct PSBTInput
SerializeToVector(s, CompactSizeWriter(PSBT_IN_HASH256), Span{hash});
s << preimage;
}
+
+ // Write taproot key sig
+ if (!m_tap_key_sig.empty()) {
+ SerializeToVector(s, PSBT_IN_TAP_KEY_SIG);
+ s << m_tap_key_sig;
+ }
+
+ // Write taproot script sigs
+ for (const auto& [pubkey_leaf, sig] : m_tap_script_sigs) {
+ const auto& [xonly, leaf_hash] = pubkey_leaf;
+ SerializeToVector(s, PSBT_IN_TAP_SCRIPT_SIG, xonly, leaf_hash);
+ s << sig;
+ }
+
+ // Write taproot leaf scripts
+ for (const auto& [leaf, control_blocks] : m_tap_scripts) {
+ const auto& [script, leaf_ver] = leaf;
+ for (const auto& control_block : control_blocks) {
+ SerializeToVector(s, PSBT_IN_TAP_LEAF_SCRIPT, Span{control_block});
+ std::vector<unsigned char> value_v(script.begin(), script.end());
+ value_v.push_back((uint8_t)leaf_ver);
+ s << value_v;
+ }
+ }
+
+ // Write taproot bip32 keypaths
+ for (const auto& [xonly, leaf_origin] : m_tap_bip32_paths) {
+ const auto& [leaf_hashes, origin] = leaf_origin;
+ SerializeToVector(s, PSBT_IN_TAP_BIP32_DERIVATION, xonly);
+ std::vector<unsigned char> value;
+ CVectorWriter s_value(s.GetType(), s.GetVersion(), value, 0);
+ s_value << leaf_hashes;
+ SerializeKeyOrigin(s_value, origin);
+ s << value;
+ }
+
+ // Write taproot internal key
+ if (!m_tap_internal_key.IsNull()) {
+ SerializeToVector(s, PSBT_IN_TAP_INTERNAL_KEY);
+ s << ToByteVector(m_tap_internal_key);
+ }
+
+ // Write taproot merkle root
+ if (!m_tap_merkle_root.IsNull()) {
+ SerializeToVector(s, PSBT_IN_TAP_MERKLE_ROOT);
+ SerializeToVector(s, m_tap_merkle_root);
+ }
}
// Write script sig
@@ -488,6 +568,106 @@ struct PSBTInput
hash256_preimages.emplace(hash, std::move(preimage));
break;
}
+ case PSBT_IN_TAP_KEY_SIG:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, input Taproot key signature already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Input Taproot key signature key is more than one byte type");
+ }
+ s >> m_tap_key_sig;
+ if (m_tap_key_sig.size() < 64) {
+ throw std::ios_base::failure("Input Taproot key path signature is shorter than 64 bytes");
+ } else if (m_tap_key_sig.size() > 65) {
+ throw std::ios_base::failure("Input Taproot key path signature is longer than 65 bytes");
+ }
+ break;
+ }
+ case PSBT_IN_TAP_SCRIPT_SIG:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, input Taproot script signature already provided");
+ } else if (key.size() != 65) {
+ throw std::ios_base::failure("Input Taproot script signature key is not 65 bytes");
+ }
+ SpanReader s_key(s.GetType(), s.GetVersion(), Span{key}.subspan(1));
+ XOnlyPubKey xonly;
+ uint256 hash;
+ s_key >> xonly;
+ s_key >> hash;
+ std::vector<unsigned char> sig;
+ s >> sig;
+ if (sig.size() < 64) {
+ throw std::ios_base::failure("Input Taproot script path signature is shorter than 64 bytes");
+ } else if (sig.size() > 65) {
+ throw std::ios_base::failure("Input Taproot script path signature is longer than 65 bytes");
+ }
+ m_tap_script_sigs.emplace(std::make_pair(xonly, hash), sig);
+ break;
+ }
+ case PSBT_IN_TAP_LEAF_SCRIPT:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, input Taproot leaf script already provided");
+ } else if (key.size() < 34) {
+ throw std::ios_base::failure("Taproot leaf script key is not at least 34 bytes");
+ } else if ((key.size() - 2) % 32 != 0) {
+ throw std::ios_base::failure("Input Taproot leaf script key's control block size is not valid");
+ }
+ std::vector<unsigned char> script_v;
+ s >> script_v;
+ if (script_v.empty()) {
+ throw std::ios_base::failure("Input Taproot leaf script must be at least 1 byte");
+ }
+ uint8_t leaf_ver = script_v.back();
+ script_v.pop_back();
+ const auto leaf_script = std::make_pair(CScript(script_v.begin(), script_v.end()), (int)leaf_ver);
+ m_tap_scripts[leaf_script].insert(std::vector<unsigned char>(key.begin() + 1, key.end()));
+ break;
+ }
+ case PSBT_IN_TAP_BIP32_DERIVATION:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, input Taproot BIP32 keypath already provided");
+ } else if (key.size() != 33) {
+ throw std::ios_base::failure("Input Taproot BIP32 keypath key is not at 33 bytes");
+ }
+ SpanReader s_key(s.GetType(), s.GetVersion(), Span{key}.subspan(1));
+ XOnlyPubKey xonly;
+ s_key >> xonly;
+ std::set<uint256> leaf_hashes;
+ uint64_t value_len = ReadCompactSize(s);
+ size_t before_hashes = s.size();
+ s >> leaf_hashes;
+ size_t after_hashes = s.size();
+ size_t hashes_len = before_hashes - after_hashes;
+ if (hashes_len > value_len) {
+ throw std::ios_base::failure("Input Taproot BIP32 keypath has an invalid length");
+ }
+ size_t origin_len = value_len - hashes_len;
+ m_tap_bip32_paths.emplace(xonly, std::make_pair(leaf_hashes, DeserializeKeyOrigin(s, origin_len)));
+ break;
+ }
+ case PSBT_IN_TAP_INTERNAL_KEY:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, input Taproot internal key already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Input Taproot internal key key is more than one byte type");
+ }
+ UnserializeFromVector(s, m_tap_internal_key);
+ break;
+ }
+ case PSBT_IN_TAP_MERKLE_ROOT:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, input Taproot merkle root already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Input Taproot merkle root key is more than one byte type");
+ }
+ UnserializeFromVector(s, m_tap_merkle_root);
+ break;
+ }
case PSBT_IN_PROPRIETARY:
{
PSBTProprietary this_prop;
@@ -532,6 +712,9 @@ struct PSBTOutput
CScript redeem_script;
CScript witness_script;
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
+ XOnlyPubKey m_tap_internal_key;
+ std::vector<std::tuple<uint8_t, uint8_t, CScript>> m_tap_tree;
+ std::map<XOnlyPubKey, std::pair<std::set<uint256>, KeyOriginInfo>> m_tap_bip32_paths;
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
std::set<PSBTProprietary> m_proprietary;
@@ -564,6 +747,36 @@ struct PSBTOutput
s << entry.value;
}
+ // Write taproot internal key
+ if (!m_tap_internal_key.IsNull()) {
+ SerializeToVector(s, PSBT_OUT_TAP_INTERNAL_KEY);
+ s << ToByteVector(m_tap_internal_key);
+ }
+
+ // Write taproot tree
+ if (!m_tap_tree.empty()) {
+ SerializeToVector(s, PSBT_OUT_TAP_TREE);
+ std::vector<unsigned char> value;
+ CVectorWriter s_value(s.GetType(), s.GetVersion(), value, 0);
+ for (const auto& [depth, leaf_ver, script] : m_tap_tree) {
+ s_value << depth;
+ s_value << leaf_ver;
+ s_value << script;
+ }
+ s << value;
+ }
+
+ // Write taproot bip32 keypaths
+ for (const auto& [xonly, leaf] : m_tap_bip32_paths) {
+ const auto& [leaf_hashes, origin] = leaf;
+ SerializeToVector(s, PSBT_OUT_TAP_BIP32_DERIVATION, xonly);
+ std::vector<unsigned char> value;
+ CVectorWriter s_value(s.GetType(), s.GetVersion(), value, 0);
+ s_value << leaf_hashes;
+ SerializeKeyOrigin(s_value, origin);
+ s << value;
+ }
+
// Write unknown things
for (auto& entry : unknown) {
s << entry.first;
@@ -624,6 +837,72 @@ struct PSBTOutput
DeserializeHDKeypaths(s, key, hd_keypaths);
break;
}
+ case PSBT_OUT_TAP_INTERNAL_KEY:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, output Taproot internal key already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Output Taproot internal key key is more than one byte type");
+ }
+ UnserializeFromVector(s, m_tap_internal_key);
+ break;
+ }
+ case PSBT_OUT_TAP_TREE:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, output Taproot tree already provided");
+ } else if (key.size() != 1) {
+ throw std::ios_base::failure("Output Taproot tree key is more than one byte type");
+ }
+ std::vector<unsigned char> tree_v;
+ s >> tree_v;
+ SpanReader s_tree(s.GetType(), s.GetVersion(), tree_v);
+ if (s_tree.empty()) {
+ throw std::ios_base::failure("Output Taproot tree must not be empty");
+ }
+ TaprootBuilder builder;
+ while (!s_tree.empty()) {
+ uint8_t depth;
+ uint8_t leaf_ver;
+ CScript script;
+ s_tree >> depth;
+ s_tree >> leaf_ver;
+ s_tree >> script;
+ if (depth > TAPROOT_CONTROL_MAX_NODE_COUNT) {
+ throw std::ios_base::failure("Output Taproot tree has as leaf greater than Taproot maximum depth");
+ }
+ 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));
+ builder.Add((int)depth, script, (int)leaf_ver, true /* track */);
+ }
+ if (!builder.IsComplete()) {
+ throw std::ios_base::failure("Output Taproot tree is malformed");
+ }
+ break;
+ }
+ case PSBT_OUT_TAP_BIP32_DERIVATION:
+ {
+ if (!key_lookup.emplace(key).second) {
+ throw std::ios_base::failure("Duplicate Key, output Taproot BIP32 keypath already provided");
+ } else if (key.size() != 33) {
+ throw std::ios_base::failure("Output Taproot BIP32 keypath key is not at 33 bytes");
+ }
+ XOnlyPubKey xonly(uint256({key.begin() + 1, key.begin() + 33}));
+ std::set<uint256> leaf_hashes;
+ uint64_t value_len = ReadCompactSize(s);
+ size_t before_hashes = s.size();
+ s >> leaf_hashes;
+ size_t after_hashes = s.size();
+ size_t hashes_len = before_hashes - after_hashes;
+ if (hashes_len > value_len) {
+ throw std::ios_base::failure("Output Taproot BIP32 keypath has an invalid length");
+ }
+ size_t origin_len = value_len - hashes_len;
+ m_tap_bip32_paths.emplace(xonly, std::make_pair(leaf_hashes, DeserializeKeyOrigin(s, origin_len)));
+ break;
+ }
case PSBT_OUT_PROPRIETARY:
{
PSBTProprietary this_prop;
diff --git a/src/pubkey.cpp b/src/pubkey.cpp
index 324f681a0a..2e37e16690 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -211,16 +211,16 @@ bool XOnlyPubKey::VerifySchnorr(const uint256& msg, Span<const unsigned char> si
return secp256k1_schnorrsig_verify(secp256k1_context_verify, sigbytes.data(), msg.begin(), 32, &pubkey);
}
-static const CHashWriter HASHER_TAPTWEAK = TaggedHash("TapTweak");
+static const HashWriter HASHER_TAPTWEAK{TaggedHash("TapTweak")};
uint256 XOnlyPubKey::ComputeTapTweakHash(const uint256* merkle_root) const
{
if (merkle_root == nullptr) {
// We have no scripts. The actual tweak does not matter, but follow BIP341 here to
// allow for reproducible tweaking.
- return (CHashWriter(HASHER_TAPTWEAK) << m_keydata).GetSHA256();
+ return (HashWriter{HASHER_TAPTWEAK} << m_keydata).GetSHA256();
} else {
- return (CHashWriter(HASHER_TAPTWEAK) << m_keydata << *merkle_root).GetSHA256();
+ return (HashWriter{HASHER_TAPTWEAK} << m_keydata << *merkle_root).GetSHA256();
}
}
@@ -365,6 +365,7 @@ void CExtPubKey::DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VE
}
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
+ if (nDepth == std::numeric_limits<unsigned char>::max()) return false;
out.nDepth = nDepth + 1;
CKeyID id = pubkey.GetID();
memcpy(out.vchFingerprint, &id, 4);
diff --git a/src/pubkey.h b/src/pubkey.h
index dfe06f834c..0485a38f72 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -218,7 +218,7 @@ public:
bool Decompress();
//! Derive BIP32 child pubkey.
- bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
+ [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
};
class XOnlyPubKey
@@ -286,6 +286,9 @@ public:
bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
bool operator!=(const XOnlyPubKey& other) const { return m_keydata != other.m_keydata; }
bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; }
+
+ //! Implement serialization without length prefixes since it is a fixed length
+ SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); }
};
struct CExtPubKey {
@@ -324,7 +327,7 @@ struct CExtPubKey {
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const;
void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]);
- bool Derive(CExtPubKey& out, unsigned int nChild) const;
+ [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild) const;
};
/** Users of this module must hold an ECCVerifyHandle. The constructor and
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 27ee9509e6..8b5da7f9f0 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -370,23 +370,21 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con
else if(type == Receive)
{
// Generate a new address to associate with given label
- CTxDestination dest;
- if(!walletModel->wallet().getNewDestination(address_type, strLabel, dest))
- {
+ auto op_dest = walletModel->wallet().getNewDestination(address_type, strLabel);
+ if (!op_dest) {
WalletModel::UnlockContext ctx(walletModel->requestUnlock());
- if(!ctx.isValid())
- {
+ if (!ctx.isValid()) {
// Unlock wallet failed or was cancelled
editStatus = WALLET_UNLOCK_FAILURE;
return QString();
}
- if(!walletModel->wallet().getNewDestination(address_type, strLabel, dest))
- {
+ op_dest = walletModel->wallet().getNewDestination(address_type, strLabel);
+ if (!op_dest) {
editStatus = KEY_GENERATION_FAILURE;
return QString();
}
}
- strAddress = EncodeDestination(dest);
+ strAddress = EncodeDestination(*op_dest);
}
else
{
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index f11ddad30f..cc01e4d54a 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -75,15 +75,15 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
Q_DECLARE_METATYPE(bool*)
Q_DECLARE_METATYPE(CAmount)
Q_DECLARE_METATYPE(SynchronizationState)
+Q_DECLARE_METATYPE(SyncType)
Q_DECLARE_METATYPE(uint256)
-using node::NodeContext;
-
static void RegisterMetaTypes()
{
// Register meta types used for QMetaObject::invokeMethod and Qt::QueuedConnection
qRegisterMetaType<bool*>();
qRegisterMetaType<SynchronizationState>();
+ qRegisterMetaType<SyncType>();
#ifdef ENABLE_WALLET
qRegisterMetaType<WalletModel*>();
#endif
@@ -96,7 +96,11 @@ static void RegisterMetaTypes()
qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
qRegisterMetaTypeStreamOperators<BitcoinUnit>("BitcoinUnit");
+#else
+ qRegisterMetaType<BitcoinUnit>("BitcoinUnit");
+#endif
}
static QString GetLangTerritory()
@@ -135,21 +139,30 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
// - First load the translator for the base language, without territory
// - Then load the more specific locale translator
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
+ const QString translation_path{QLibraryInfo::location(QLibraryInfo::TranslationsPath)};
+#else
+ const QString translation_path{QLibraryInfo::path(QLibraryInfo::TranslationsPath)};
+#endif
// Load e.g. qt_de.qm
- if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ if (qtTranslatorBase.load("qt_" + lang, translation_path)) {
QApplication::installTranslator(&qtTranslatorBase);
+ }
// Load e.g. qt_de_DE.qm
- if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ if (qtTranslator.load("qt_" + lang_territory, translation_path)) {
QApplication::installTranslator(&qtTranslator);
+ }
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
- if (translatorBase.load(lang, ":/translations/"))
+ if (translatorBase.load(lang, ":/translations/")) {
QApplication::installTranslator(&translatorBase);
+ }
// Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
- if (translator.load(lang_territory, ":/translations/"))
+ if (translator.load(lang_territory, ":/translations/")) {
QApplication::installTranslator(&translator);
+ }
}
static bool InitSettings()
@@ -517,9 +530,11 @@ int GuiMain(int argc, char* argv[])
Q_INIT_RESOURCE(bitcoin);
Q_INIT_RESOURCE(bitcoin_locale);
+#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
// Generate high-dpi pixmaps
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
#if defined(QT_QPA_PLATFORM_ANDROID)
QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc
index b6dca18be3..e87cfe21e2 100644
--- a/src/qt/bitcoin_locale.qrc
+++ b/src/qt/bitcoin_locale.qrc
@@ -19,7 +19,6 @@
<file alias="es_CL">locale/bitcoin_es_CL.qm</file>
<file alias="es_CO">locale/bitcoin_es_CO.qm</file>
<file alias="es_DO">locale/bitcoin_es_DO.qm</file>
- <file alias="es_MX">locale/bitcoin_es_MX.qm</file>
<file alias="es_VE">locale/bitcoin_es_VE.qm</file>
<file alias="et">locale/bitcoin_et.qm</file>
<file alias="eu">locale/bitcoin_eu.qm</file>
@@ -32,6 +31,7 @@
<file alias="gl">locale/bitcoin_gl.qm</file>
<file alias="gl_ES">locale/bitcoin_gl_ES.qm</file>
<file alias="gu">locale/bitcoin_gu.qm</file>
+ <file alias="ha">locale/bitcoin_ha.qm</file>
<file alias="he">locale/bitcoin_he.qm</file>
<file alias="hr">locale/bitcoin_hr.qm</file>
<file alias="hu">locale/bitcoin_hu.qm</file>
@@ -44,6 +44,7 @@
<file alias="kl">locale/bitcoin_kl.qm</file>
<file alias="km">locale/bitcoin_km.qm</file>
<file alias="ko">locale/bitcoin_ko.qm</file>
+ <file alias="ku">locale/bitcoin_ku.qm</file>
<file alias="ku_IQ">locale/bitcoin_ku_IQ.qm</file>
<file alias="ky">locale/bitcoin_ky.qm</file>
<file alias="la">locale/bitcoin_la.qm</file>
@@ -59,6 +60,7 @@
<file alias="ne">locale/bitcoin_ne.qm</file>
<file alias="nl">locale/bitcoin_nl.qm</file>
<file alias="no">locale/bitcoin_no.qm</file>
+ <file alias="pa">locale/bitcoin_pa.qm</file>
<file alias="pam">locale/bitcoin_pam.qm</file>
<file alias="pl">locale/bitcoin_pl.qm</file>
<file alias="pt">locale/bitcoin_pt.qm</file>
@@ -79,10 +81,13 @@
<file alias="ta">locale/bitcoin_ta.qm</file>
<file alias="te">locale/bitcoin_te.qm</file>
<file alias="th">locale/bitcoin_th.qm</file>
+ <file alias="tk">locale/bitcoin_tk.qm</file>
+ <file alias="tl">locale/bitcoin_tl.qm</file>
<file alias="tr">locale/bitcoin_tr.qm</file>
<file alias="ug">locale/bitcoin_ug.qm</file>
<file alias="uk">locale/bitcoin_uk.qm</file>
<file alias="ur">locale/bitcoin_ur.qm</file>
+ <file alias="uz">locale/bitcoin_uz.qm</file>
<file alias="uz@Cyrl">locale/bitcoin_uz@Cyrl.qm</file>
<file alias="uz@Latn">locale/bitcoin_uz@Latn.qm</file>
<file alias="vi">locale/bitcoin_vi.qm</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 6fea8e1cba..18d374311a 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -47,6 +47,7 @@
#include <QCursor>
#include <QDateTime>
#include <QDragEnterEvent>
+#include <QInputDialog>
#include <QKeySequence>
#include <QListWidget>
#include <QMenu>
@@ -348,6 +349,12 @@ void BitcoinGUI::createActions()
m_create_wallet_action->setEnabled(false);
m_create_wallet_action->setStatusTip(tr("Create a new wallet"));
+ //: Name of the menu item that restores wallet from a backup file.
+ m_restore_wallet_action = new QAction(tr("Restore Wallet…"), this);
+ m_restore_wallet_action->setEnabled(false);
+ //: Status tip for Restore Wallet menu item
+ m_restore_wallet_action->setStatusTip(tr("Restore a wallet from a backup file"));
+
m_close_all_wallets_action = new QAction(tr("Close All Wallets…"), this);
m_close_all_wallets_action->setStatusTip(tr("Close all wallets"));
@@ -412,6 +419,31 @@ void BitcoinGUI::createActions()
action->setEnabled(false);
}
});
+ connect(m_restore_wallet_action, &QAction::triggered, [this] {
+ //: Name of the wallet data file format.
+ QString name_data_file = tr("Wallet Data");
+
+ //: The title for Restore Wallet File Windows
+ QString title_windows = tr("Load Wallet Backup");
+
+ QString backup_file = GUIUtil::getOpenFileName(this, title_windows, QString(), name_data_file + QLatin1String(" (*.dat)"), nullptr);
+ if (backup_file.isEmpty()) return;
+
+ bool wallet_name_ok;
+ /*: Title of pop-up window shown when the user is attempting to
+ restore a wallet. */
+ QString title = tr("Restore Wallet");
+ //: Label of the input field where the name of the wallet is entered.
+ QString label = tr("Wallet Name");
+ QString wallet_name = QInputDialog::getText(this, title, label, QLineEdit::Normal, "", &wallet_name_ok);
+ if (!wallet_name_ok || wallet_name.isEmpty()) return;
+
+ auto activity = new RestoreWalletActivity(m_wallet_controller, this);
+ connect(activity, &RestoreWalletActivity::restored, this, &BitcoinGUI::setCurrentWallet, Qt::QueuedConnection);
+
+ 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] {
m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
});
@@ -450,8 +482,10 @@ void BitcoinGUI::createMenuBar()
file->addAction(m_close_wallet_action);
file->addAction(m_close_all_wallets_action);
file->addSeparator();
- file->addAction(openAction);
file->addAction(backupWalletAction);
+ file->addAction(m_restore_wallet_action);
+ file->addSeparator();
+ file->addAction(openAction);
file->addAction(signMessageAction);
file->addAction(verifyMessageAction);
file->addAction(m_load_psbt_action);
@@ -478,7 +512,7 @@ void BitcoinGUI::createMenuBar()
connect(minimize_action, &QAction::triggered, [] {
QApplication::activeWindow()->showMinimized();
});
- connect(qApp, &QApplication::focusWindowChanged, [minimize_action] (QWindow* window) {
+ connect(qApp, &QApplication::focusWindowChanged, this, [minimize_action] (QWindow* window) {
minimize_action->setEnabled(window != nullptr && (window->flags() & Qt::Dialog) != Qt::Dialog && window->windowState() != Qt::WindowMinimized);
});
@@ -493,7 +527,7 @@ void BitcoinGUI::createMenuBar()
}
});
- connect(qApp, &QApplication::focusWindowChanged, [zoom_action] (QWindow* window) {
+ connect(qApp, &QApplication::focusWindowChanged, this, [zoom_action] (QWindow* window) {
zoom_action->setEnabled(window != nullptr);
});
#endif
@@ -581,8 +615,8 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
connect(_clientModel, &ClientModel::numConnectionsChanged, this, &BitcoinGUI::setNumConnections);
connect(_clientModel, &ClientModel::networkActiveChanged, this, &BitcoinGUI::setNetworkActive);
- modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time));
- setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), tip_info->verification_progress, false, SynchronizationState::INIT_DOWNLOAD);
+ modalOverlay->setKnownBestHeight(tip_info->header_height, QDateTime::fromSecsSinceEpoch(tip_info->header_time), /*presync=*/false);
+ setNumBlocks(tip_info->block_height, QDateTime::fromSecsSinceEpoch(tip_info->block_time), tip_info->verification_progress, SyncType::BLOCK_SYNC, SynchronizationState::INIT_DOWNLOAD);
connect(_clientModel, &ClientModel::numBlocksChanged, this, &BitcoinGUI::setNumBlocks);
// Receive and report messages from client model
@@ -642,6 +676,7 @@ void BitcoinGUI::setWalletController(WalletController* wallet_controller)
m_create_wallet_action->setEnabled(true);
m_open_wallet_action->setEnabled(true);
m_open_wallet_action->setMenu(m_open_wallet_menu);
+ m_restore_wallet_action->setEnabled(true);
GUIUtil::ExceptionSafeConnect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
@@ -991,6 +1026,13 @@ void BitcoinGUI::updateHeadersSyncProgressLabel()
progressBarLabel->setText(tr("Syncing Headers (%1%)…").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
}
+void BitcoinGUI::updateHeadersPresyncProgressLabel(int64_t height, const QDateTime& blockDate)
+{
+ int estHeadersLeft = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
+ if (estHeadersLeft > HEADER_HEIGHT_DELTA_SYNC)
+ progressBarLabel->setText(tr("Pre-syncing Headers (%1%)…").arg(QString::number(100.0 / (height+estHeadersLeft)*height, 'f', 1)));
+}
+
void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab)
{
if (!clientModel || !clientModel->getOptionsModel())
@@ -999,11 +1041,12 @@ void BitcoinGUI::openOptionsDialogWithTab(OptionsDialog::Tab tab)
auto dlg = new OptionsDialog(this, enableWallet);
connect(dlg, &OptionsDialog::quitOnReset, this, &BitcoinGUI::quitRequested);
dlg->setCurrentTab(tab);
+ dlg->setClientModel(clientModel);
dlg->setModel(clientModel->getOptionsModel());
GUIUtil::ShowModalDialogAsynchronously(dlg);
}
-void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state)
+void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state)
{
// Disabling macOS App Nap on initial sync, disk and reindex operations.
#ifdef Q_OS_MACOS
@@ -1016,8 +1059,8 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
if (modalOverlay)
{
- if (header)
- modalOverlay->setKnownBestHeight(count, blockDate);
+ if (synctype != SyncType::BLOCK_SYNC)
+ modalOverlay->setKnownBestHeight(count, blockDate, synctype == SyncType::HEADER_PRESYNC);
else
modalOverlay->tipUpdate(count, blockDate, nVerificationProgress);
}
@@ -1031,7 +1074,10 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
enum BlockSource blockSource = clientModel->getBlockSource();
switch (blockSource) {
case BlockSource::NETWORK:
- if (header) {
+ if (synctype == SyncType::HEADER_PRESYNC) {
+ updateHeadersPresyncProgressLabel(count, blockDate);
+ return;
+ } else if (synctype == SyncType::HEADER_SYNC) {
updateHeadersSyncProgressLabel();
return;
}
@@ -1039,7 +1085,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
updateHeadersSyncProgressLabel();
break;
case BlockSource::DISK:
- if (header) {
+ if (synctype != SyncType::BLOCK_SYNC) {
progressBarLabel->setText(tr("Indexing blocks on disk…"));
} else {
progressBarLabel->setText(tr("Processing blocks on disk…"));
@@ -1049,7 +1095,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
progressBarLabel->setText(tr("Reindexing blocks on disk…"));
break;
case BlockSource::NONE:
- if (header) {
+ if (synctype != SyncType::BLOCK_SYNC) {
return;
}
progressBarLabel->setText(tr("Connecting to peers…"));
@@ -1318,6 +1364,12 @@ void BitcoinGUI::setEncryptionStatus(int status)
{
switch(status)
{
+ case WalletModel::NoKeys:
+ labelWalletEncryptionIcon->hide();
+ encryptWalletAction->setChecked(false);
+ changePassphraseAction->setEnabled(false);
+ encryptWalletAction->setEnabled(false);
+ break;
case WalletModel::Unencrypted:
labelWalletEncryptionIcon->hide();
encryptWalletAction->setChecked(false);
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 6272d5d947..912e9b95aa 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -10,6 +10,7 @@
#endif
#include <qt/bitcoinunits.h>
+#include <qt/clientmodel.h>
#include <qt/guiutil.h>
#include <qt/optionsdialog.h>
@@ -28,7 +29,6 @@
#include <memory>
-class ClientModel;
class NetworkStyle;
class Notificator;
class OptionsModel;
@@ -157,6 +157,7 @@ private:
QAction* m_create_wallet_action{nullptr};
QAction* m_open_wallet_action{nullptr};
QMenu* m_open_wallet_menu{nullptr};
+ QAction* m_restore_wallet_action{nullptr};
QAction* m_close_wallet_action{nullptr};
QAction* m_close_all_wallets_action{nullptr};
QAction* m_wallet_selector_label_action = nullptr;
@@ -207,6 +208,7 @@ private:
void updateNetworkState();
void updateHeadersSyncProgressLabel();
+ void updateHeadersPresyncProgressLabel(int64_t height, const QDateTime& blockDate);
/** Open the OptionsDialog on the specified tab index */
void openOptionsDialogWithTab(OptionsDialog::Tab tab);
@@ -225,7 +227,7 @@ public Q_SLOTS:
/** Set network state shown in the UI */
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, bool headers, SynchronizationState sync_state);
+ void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state);
/** 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 ba804d6955..3df4d4d921 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -14,9 +14,28 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring "
"a backup."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"%s request to listen on port %u. This port is considered \"bad\" and thus it "
+"is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports."
+"md for details and a full list."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"-maxtxfee is set very high! Fees this large could be paid on a single "
"transaction."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"-reindex-chainstate option is not compatible with -blockfilterindex. Please "
+"temporarily disable blockfilterindex while using -reindex-chainstate, or "
+"replace -reindex-chainstate with -reindex to fully rebuild all indexes."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"-reindex-chainstate option is not compatible with -coinstatsindex. Please "
+"temporarily disable coinstatsindex while using -reindex-chainstate, or "
+"replace -reindex-chainstate with -reindex to fully rebuild all indexes."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"-reindex-chainstate option is not compatible with -txindex. Please "
+"temporarily disable txindex while using -reindex-chainstate, or replace -"
+"reindex-chainstate with -reindex to fully rebuild all indexes."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Assumed-valid: last wallet synchronisation goes beyond available block data. "
+"You need to wait for the background validation chain to download more blocks."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Cannot downgrade wallet from version %i to version %i. Wallet version "
"unchanged."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -41,6 +60,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error reading %s! Transaction data may be missing or incorrect. Rescanning "
"wallet."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Error: Address book data in wallet cannot be identified to belong to "
+"migrated wallets"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: Dumpfile format record is incorrect. Got \"%s\", expected \"format\"."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: Dumpfile identifier record is incorrect. Got \"%s\", expected \"%s\"."),
@@ -48,10 +70,20 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: Dumpfile version is not supported. This version of bitcoin-wallet "
"only supports version 1 dumpfiles. Got dumpfile with version %s"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Error: Duplicate descriptors created during migration. Your wallet may be "
+"corrupted."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and "
"\"bech32\" address types"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Error: Listening for incoming connections failed (listen returned error %s)"),
+"Error: Transaction %s in wallet cannot be identified to belong to migrated "
+"wallets"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Error: Unable to produce descriptors for this legacy wallet. Make sure the "
+"wallet is unlocked first"),
+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", ""
"Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -"
"fallbackfee."),
@@ -59,6 +91,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"File %s already exists. If you are sure this is what you want, move it out "
"of the way first."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet "
+"forbids connections to IPv4/IPv6"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay "
"fee of %s to prevent stuck transactions)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -77,6 +112,13 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"No wallet file format provided. To use createfromdump, -format=<format> must "
"be provided."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
+"reaching the Tor network is explicitly forbidden: -onion=0"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"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"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Please check that your computer's date and time are correct! If your clock "
"is wrong, %s will not work properly."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -85,6 +127,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Prune configured below the minimum of %d MiB. Please use a higher number."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Prune mode is incompatible with -reindex-chainstate. Use full -reindex "
+"instead."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Prune: last wallet synchronisation goes beyond pruned data. You need to -"
"reindex (download the whole blockchain again in case of pruned node)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -129,6 +174,21 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Unknown wallet file format \"%s\" provided. Please provide one of \"bdb\" or "
"\"sqlite\"."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Unrecognized descriptor found. Loading wallet %s\n"
+"\n"
+"The wallet might had been created on a newer version.\n"
+"Please try running the latest software version.\n"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Unsupported category-specific logging level -loglevel=%s. Expected -"
+"loglevel=<category>:<loglevel>. Valid categories: %s. Valid loglevels: %s."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Unsupported chainstate database format found. Please restart with -reindex-"
+"chainstate. This will rebuild the chainstate database."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Wallet created successfully. The legacy wallet type is being deprecated and "
+"support for creating and opening legacy wallets will be removed in the "
+"future."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: Dumpfile wallet format \"%s\" does not match command line specified "
"format \"%s\"."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -142,6 +202,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
QT_TRANSLATE_NOOP("bitcoin-core", ""
"You need to rebuild the database using -reindex to go back to unpruned "
"mode. This will redownload the entire blockchain"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"\n"
+"Unable to cleanup failed migration"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"\n"
+"Unable to restore backup of wallet."),
QT_TRANSLATE_NOOP("bitcoin-core", "%s is set very high!"),
QT_TRANSLATE_NOOP("bitcoin-core", "-maxmempool must be at least %d MB"),
QT_TRANSLATE_NOOP("bitcoin-core", "A fatal internal error occurred, see debug.log for details"),
@@ -169,16 +235,25 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error loading block database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error opening block database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error reading from database, shutting down."),
QT_TRANSLATE_NOOP("bitcoin-core", "Error reading next record from wallet database"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Error upgrading chainstate database"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Could not add watchonly tx to watchonly wallet"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Could not delete watchonly transactions"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Couldn't create cursor into database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low for %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Dumpfile checksum does not match. Computed %s, expected %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Failed to create new watchonly wallet"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Got key that was not hex: %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Got value that was not hex: %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Keypool ran out, please call keypoolrefill first"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Missing checksum"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: No %s addresses available."),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Not all watchonly txs could be deleted"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: This wallet already uses SQLite"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: This wallet is already a descriptor wallet"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unable to begin reading all records in the database"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unable to make a backup of your wallet"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unable to parse version %u as a uint32_t"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unable to read all records in the database"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unable to remove watchonly address book data"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unable to write record to new wallet"),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to rescan the wallet during initialization"),
@@ -199,6 +274,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -discardfee=<amount>: '%s'
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -fallbackfee=<amount>: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid netmask specified in -whitelist: '%s'"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Listening for incoming connections failed (listen returned error %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Loading P2P addresses…"),
QT_TRANSLATE_NOOP("bitcoin-core", "Loading banlist…"),
QT_TRANSLATE_NOOP("bitcoin-core", "Loading block index…"),
@@ -207,10 +283,8 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Missing amount"),
QT_TRANSLATE_NOOP("bitcoin-core", "Missing solving data for estimating transaction size"),
QT_TRANSLATE_NOOP("bitcoin-core", "Need to specify a port with -whitebind: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "No addresses available"),
-QT_TRANSLATE_NOOP("bitcoin-core", "No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>."),
QT_TRANSLATE_NOOP("bitcoin-core", "Not enough file descriptors available."),
QT_TRANSLATE_NOOP("bitcoin-core", "Prune cannot be configured with a negative value."),
-QT_TRANSLATE_NOOP("bitcoin-core", "Prune mode is incompatible with -coinstatsindex."),
QT_TRANSLATE_NOOP("bitcoin-core", "Prune mode is incompatible with -txindex."),
QT_TRANSLATE_NOOP("bitcoin-core", "Pruning blockstore…"),
QT_TRANSLATE_NOOP("bitcoin-core", "Reducing -maxconnections from %d to %d, because of system limitations."),
@@ -241,21 +315,24 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Transaction has too long of a mempool chain")
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction must have at least one recipient"),
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction needs a change address, but we can't generate it."),
QT_TRANSLATE_NOOP("bitcoin-core", "Transaction too large"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Unable to allocate memory for -maxsigcachesize: '%s' MiB"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer. %s is probably already running."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to create the PID file '%s': %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Unable to find UTXO for external input"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to generate initial keys"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to generate keys"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to open %s for writing"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to parse -maxuploadtarget: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to start HTTP server. See debug log for details."),
+QT_TRANSLATE_NOOP("bitcoin-core", "Unable to unload the wallet before migrating"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown -blockfilterindex value %s."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown address type '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown change type '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown new rules activated (versionbit %i)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported global logging level -loglevel=%s. Valid values: %s."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported logging category %s=%s."),
-QT_TRANSLATE_NOOP("bitcoin-core", "Upgrading UTXO database"),
QT_TRANSLATE_NOOP("bitcoin-core", "User Agent comment (%s) contains unsafe characters."),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks…"),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet(s)…"),
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index f41da519df..092ffe7e5b 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -215,26 +215,26 @@ QString ClientModel::blocksDir() const
return GUIUtil::PathToQString(gArgs.GetBlocksDirPath());
}
-void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header)
+void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, SyncType synctype)
{
- if (header) {
+ if (synctype == SyncType::HEADER_SYNC) {
// cache best headers time and height to reduce future cs_main locks
cachedBestHeaderHeight = tip.block_height;
cachedBestHeaderTime = tip.block_time;
- } else {
+ } else if (synctype == SyncType::BLOCK_SYNC) {
m_cached_num_blocks = tip.block_height;
WITH_LOCK(m_cached_tip_mutex, m_cached_tip_blocks = tip.block_hash;);
}
// Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex.
- const bool throttle = (sync_state != SynchronizationState::POST_INIT && !header) || sync_state == SynchronizationState::INIT_REINDEX;
+ const bool throttle = (sync_state != SynchronizationState::POST_INIT && synctype == SyncType::BLOCK_SYNC) || sync_state == SynchronizationState::INIT_REINDEX;
const int64_t now = throttle ? GetTimeMillis() : 0;
- int64_t& nLastUpdateNotification = header ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
+ int64_t& nLastUpdateNotification = synctype != SyncType::BLOCK_SYNC ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
if (throttle && now < nLastUpdateNotification + count_milliseconds(MODEL_UPDATE_DELAY)) {
return;
}
- Q_EMIT numBlocksChanged(tip.block_height, QDateTime::fromSecsSinceEpoch(tip.block_time), verification_progress, header, sync_state);
+ Q_EMIT numBlocksChanged(tip.block_height, QDateTime::fromSecsSinceEpoch(tip.block_time), verification_progress, synctype, sync_state);
nLastUpdateNotification = now;
}
@@ -264,11 +264,11 @@ void ClientModel::subscribeToCoreSignals()
});
m_handler_notify_block_tip = m_node.handleNotifyBlockTip(
[this](SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress) {
- TipChanged(sync_state, tip, verification_progress, /*header=*/false);
+ TipChanged(sync_state, tip, verification_progress, SyncType::BLOCK_SYNC);
});
m_handler_notify_header_tip = m_node.handleNotifyHeaderTip(
- [this](SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress) {
- TipChanged(sync_state, tip, verification_progress, /*header=*/true);
+ [this](SynchronizationState sync_state, interfaces::BlockTip tip, bool presync) {
+ TipChanged(sync_state, tip, /*verification_progress=*/0.0, presync ? SyncType::HEADER_PRESYNC : SyncType::HEADER_SYNC);
});
}
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 81f03a58ec..4a6abd6a76 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -37,6 +37,12 @@ enum class BlockSource {
NETWORK
};
+enum class SyncType {
+ HEADER_PRESYNC,
+ HEADER_SYNC,
+ BLOCK_SYNC
+};
+
enum NumConnections {
CONNECTIONS_NONE = 0,
CONNECTIONS_IN = (1U << 0),
@@ -105,13 +111,13 @@ private:
//! A thread to interact with m_node asynchronously
QThread* const m_thread;
- void TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, bool header) EXCLUSIVE_LOCKS_REQUIRED(!m_cached_tip_mutex);
+ void TipChanged(SynchronizationState sync_state, interfaces::BlockTip tip, double verification_progress, SyncType synctype) EXCLUSIVE_LOCKS_REQUIRED(!m_cached_tip_mutex);
void subscribeToCoreSignals();
void unsubscribeFromCoreSignals();
Q_SIGNALS:
void numConnectionsChanged(int count);
- void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state);
+ void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType header, SynchronizationState sync_state);
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes);
void networkActiveChanged(bool networkActive);
void alertsChanged(const QString &warnings);
diff --git a/src/qt/forms/intro.ui b/src/qt/forms/intro.ui
index a1e94f99e6..9ab91f6aa9 100644
--- a/src/qt/forms/intro.ui
+++ b/src/qt/forms/intro.ui
@@ -203,7 +203,7 @@
<item>
<widget class="QLabel" name="lblExplanation1">
<property name="text">
- <string>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</string>
+ <string>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.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 2551be0af3..6e88b57e08 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -428,7 +428,7 @@ void openDebugLogfile()
bool openBitcoinConf()
{
- fs::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
+ fs::path pathConfig = GetConfigFile(gArgs.GetPathArg("-conf", BITCOIN_CONF_FILENAME));
/* Create the file */
std::ofstream configFile{pathConfig, std::ios_base::app};
@@ -615,9 +615,10 @@ bool SetStartOnSystemStartup(bool fAutoStart)
else
{
char pszExePath[MAX_PATH+1];
- ssize_t r = readlink("/proc/self/exe", pszExePath, sizeof(pszExePath) - 1);
- if (r == -1)
+ ssize_t r = readlink("/proc/self/exe", pszExePath, sizeof(pszExePath));
+ if (r == -1 || r > MAX_PATH) {
return false;
+ }
pszExePath[r] = '\0';
fs::create_directories(GetAutostartDir());
@@ -982,7 +983,7 @@ void PrintSlotException(
std::string description = sender->metaObject()->className();
description += "->";
description += receiver->metaObject()->className();
- PrintExceptionContinue(exception, description.c_str());
+ PrintExceptionContinue(exception, description);
}
void ShowModalDialogAsynchronously(QDialog* dialog)
diff --git a/src/qt/locale/bitcoin_am.ts b/src/qt/locale/bitcoin_am.ts
index 09462a2703..b836bd7dfd 100644
--- a/src/qt/locale/bitcoin_am.ts
+++ b/src/qt/locale/bitcoin_am.ts
@@ -359,6 +359,11 @@
<translation type="unfinished">መደበኛ ዋሌት</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">ዋሌት ስáˆ</translation>
+ </message>
+ <message>
<source>Zoom</source>
<translation type="unfinished">እሳድáŒ</translation>
</message>
@@ -484,6 +489,27 @@
<translation type="unfinished">ቢትኮይን</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts
index 1b4b088647..650a0fdfa1 100644
--- a/src/qt/locale/bitcoin_ar.ts
+++ b/src/qt/locale/bitcoin_ar.ts
@@ -23,7 +23,7 @@
</message>
<message>
<source>C&amp;lose</source>
- <translation type="unfinished">غلق</translation>
+ <translation type="unfinished">أغلق</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
@@ -51,7 +51,7 @@
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation type="unfinished">إختر العنوان الرقمي اللذي سيحصل على العملات</translation>
+ <translation type="unfinished">اختر العنوان الذي تود إرسال العملات إليه</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -241,6 +241,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">مل٠الاعدادات %1 قد يكون تال٠او غير صالح</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">استثناء هارب</translation>
</message>
@@ -353,12 +357,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%nثانية</numerusform>
+ <numerusform>%nثانية </numerusform>
+ <numerusform>%nثانية</numerusform>
+ <numerusform>%n ثواني</numerusform>
+ <numerusform>%nثواني </numerusform>
+ <numerusform>%n ثواني</numerusform>
</translation>
</message>
<message numerus="yes">
@@ -540,6 +544,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">لايمكن الكتابة على دليل البيانات '%s'؛ تحقق من السماحيات. </translation>
</message>
<message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s طلب الاستماع على منÙØ° %u. يعتبر منÙذه "سيئًا" وبالتالي Ùمن غير المحتمل أن يتصل به أي من أقران Bitcoin Core. انظر الى doc / p2p-bad-ports.md للحصول على التÙاصيل والقائمة الكاملة.</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Ùشل ÙÙŠ إعادة تسمية مل٠peers.dat غير صالح. يرجى نقلها أو حذÙها وحاول مرة أخرى.</translation>
+ </message>
+ <message>
<source>Copyright (C) %i-%i</source>
<translation type="unfinished">حقوق الطبع والنشر (C) %i-%i</translation>
</message>
@@ -600,10 +612,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">خطأ قراءة السجل التالي من قاعدة بيانات المحÙظة</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">خطأ ÙÙŠ ترقية قاعدة بيانات chainstate</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">خطأ : لا يمكن انشاء مؤشر ضمن قاعدة البيانات </translation>
</message>
@@ -814,10 +822,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">شبكة مجهولة عرÙت حددت ÙÙŠ -onlynet: '%s'</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">ترقية قاعدة بيانات UTXO</translation>
- </message>
- <message>
<source>Verifying blocks…</source>
<translation type="unfinished">جار التحقق من الكتل...</translation>
</message>
@@ -1105,6 +1109,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">اغلق المحÙظة</translation>
</message>
<message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">استعادة محÙظة من مل٠النسخ الاحتياطي</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">إغلاق جميع المحاÙظ ...</translation>
</message>
@@ -1129,6 +1138,21 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">المحÙظة الرقمية غير متوÙرة</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">بيانات المحÙظة</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">استعادة المحÙظة</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">إسم المحÙظة</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">ناÙذه</translation>
</message>
@@ -1436,7 +1460,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">لا يمكن سرد الموقعين</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenWalletActivity</name>
<message>
@@ -1463,6 +1487,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">استعادة المحÙظة</translation>
+ </message>
+ </context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1637,13 +1669,38 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Bitcoin</source>
<translation type="unfinished">بتكوين</translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(من %1 الجيجابايت المطلوبة)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 مطلوب غيغابايت للسلسلة الكاملة)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1694,10 +1751,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">بما انه هذه اول مرة لانطلاق هذا البرنامج, Ùيمكنك ان تختار اين سيخزن %1 بياناته</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">عند النقر على "مواÙÙ‚" ØŒ سيبدأ %1 ÙÙŠ تنزيل ومعالجة سلسلة الكتل %4 الكاملة (%2 جيجابايت) بدءًا من المعاملات الأقدم ÙÙŠ %3 عند تشغيل %4 ÙÙŠ البداية.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">تقييد تخزين سلسلة الكتل إلى</translation>
</message>
@@ -1806,7 +1859,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">مجهول. مزامنة الرؤوس (%1،%2٪) ...</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2054,10 +2107,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">المضمنة "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">يتم تجاوز الخيارات المعينة ÙÙŠ مربع الحوار هذا بواسطة سطر الأوامر أو ÙÙŠ مل٠التكوين:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">تم</translation>
</message>
@@ -2080,14 +2129,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">تأكيد استعادة الخيارات</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">يتطلب إعادة تشغيل العميل لتÙعيل التغييرات.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">سو٠يتم إيقا٠العميل تماماً. هل تريد الإستمرار؟</translation>
</message>
<message>
@@ -3288,10 +3340,6 @@ If you are receiving this error you should request the merchant provide a BIP21
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">تعتبر الرسوم الأعلى من %1 رسوماً باهظة.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">انتهاء صلاحية طلب الدÙع.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3375,14 +3423,6 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">الرسائل</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">هذا طلب دÙع لم يتم مصادقته.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">هذا طلب دÙع تمت مصادقته.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">أدخل تسمية لهذا العنوان لإضاÙته إلى قائمة العناوين المستخدمة</translation>
</message>
@@ -3390,14 +3430,6 @@ If you are receiving this error you should request the merchant provide a BIP21
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">الرسالة التي تم إرÙاقها مع البتكوين: العنوان الذي سيتم تخزينه مع المعاملة للرجوع إليه. ملاحظة: لن يتم إرسال هذه الرسالة عبر شبكة البتكوين.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">ادÙع &amp;الى :</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">مذكرة:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3564,26 +3596,22 @@ If you are receiving this error you should request the merchant provide a BIP21
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">تعارضت مع معاملة لديها %1 تأكيدات</translation>
</message>
<message>
- <source>in memory pool</source>
- <translation type="unfinished">ÙÙŠ تجمع الذاكرة</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ليس ÙÙŠ تجمع الذاكرة</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">مهجور</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">غير مؤكدة/%1</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">تأكيد %1</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_az.ts b/src/qt/locale/bitcoin_az.ts
index 6b1d4072a8..5fda74d5f2 100644
--- a/src/qt/locale/bitcoin_az.ts
+++ b/src/qt/locale/bitcoin_az.ts
@@ -92,6 +92,11 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<translation type="unfinished">Ünvan siyahısını ixrac et</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Vergüllə ayrılmış fayl</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">Ünvan siyahısını %1 daxilində saxlamağı sınayarkən xəta baş verdi. Zəhmət olmasa yenidən sınayın.</translation>
@@ -159,20 +164,68 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<translation type="unfinished">Pulqabı şifrələməsini təsdiqlə</translation>
</message>
<message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation type="unfinished">XÉ™bÉ™rdarlıq: ÆgÉ™r siz pulqabınızı ÅŸifrÉ™dÉ™n çıxarsanız vÉ™ ÅŸifrÉ™li sözü itirmiÅŸ olsanız &lt;b&gt;BÃœTÃœN BÄ°TCOÄ°NLÆRÄ°NÄ°ZÄ° Ä°TÄ°RÆCÆKSÄ°NÄ°Z&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">Pulqabınızı şifrədən çıxarmaq istədiyinizə əminsiniz?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">Pulqabı şifrələndi.</translation>
+ </message>
+ <message>
+ <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">Pulqabı üçün yeni şifrəli sözü daxil edin.&lt;br/&gt;Lütfən &lt;b&gt;on və daha çox qarışıq simvollardan&lt;/b&gt; və ya &lt;b&gt;səkkiz və daha çox sayda sözdən&lt;/b&gt; ibarət şifrəli söz istifadə edin.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation type="unfinished">Pulqabı üçün köhnə şifrəli sözü və yeni şifrəli sözü daxil edin</translation>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation type="unfinished">Unutmayın ki, cüzdanınızın şifrələməsi bitcoinlərinizi kompüterinizə zərərli proqram tərəfindən oğurlanmaqdan tamamilə qoruya bilməz.</translation>
+ <translation type="unfinished">Unutmayın ki, pulqabınızın şifrələməsi bitcoinlərinizi kompüterinizə zərərli proqram tərəfindən oğurlanmaqdan tamamilə qoruya bilməz.</translation>
</message>
<message>
<source>Wallet to be encrypted</source>
- <translation type="unfinished">Cüzdan şifrələnəcək</translation>
+ <translation type="unfinished">Pulqabı şifrələnəcək</translation>
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation type="unfinished">Cüzdanınız şifrələnmək üzrədir.</translation>
+ <translation type="unfinished">Pulqabınız şifrələnmək üzrədir.</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation type="unfinished">Cüzdanınız artıq şifrələnib.</translation>
+ <translation type="unfinished">Pulqabınız artıq şifrələnib.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation type="unfinished">VACİBDİR: Pulqabınızın əvvəlki ehtiyyat nüsxələri yenicə yaradılan şifrələnmiş cüzdan ilə əvəz olunmalıdır. Təhlükəsizlik baxımından yeni şifrələnmiş pulqabını işə salan kimi əvvəlki şifrəsi açılmış pulqabının ehtiyyat nüsxələri qeyri-işlək olacaqdır.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation type="unfinished">Cüzdanın şifrələnməsi baş tutmadı</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation type="unfinished">Daxili xəta səbəbindən cüzdanın şifrələnməsi baş tutmadı. Cüzdanınız şifrələnmədi.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">Təqdim etdiyiniz şifrəli söz uyğun deyil.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation type="unfinished">Cüzdanın şifrədən çıxarılması baş tutmadı</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation type="unfinished">Cüzdanı şifrədən çıxarmaq üçün daxil etdiyiniz şifrəli söz səhvdir.</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished">Cüzdanın şifrəli sözü uğurla dəyişdirildi.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
@@ -180,7 +233,67 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
</message>
</context>
<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>Banned Until</source>
+ <translation type="unfinished">QadaÄŸan edildi</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Ola bilsin ki, %1 faylı zədələnib və ya yararsızdır.</translation>
+ </message>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">İdarə edilə bilməyən istisna</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">Ciddi xəta baş verdi. %1 təhlükəsiz davam etdirilə bilməz və bağlanacaqdır.</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">Daxili xəta</translation>
+ </message>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">Daxili xəta baş verdi. %1 təhlükəsiz davam etməyə cəhd edəcək. Bu gözlənilməz bir xətadır və onun haqqında aşağıdakı şəkildə bildirmək olar.</translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
+ <message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Siz ayarları dəyərləri ilkin dəyərlərinə sıfırlamaq istəyirsiniz, yoxsa dəyişiklik etmədən bu əməliyyatı ləğv etmək istəyirsiniz?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Ciddi xəta baş verdi. Ayarlar faylının yazılabilən olduğunu yoxlayın və ya -nonsettings (ayarlarsız) parametri ilə işə salın.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation type="unfinished">Xəta: Göstərilmiş verilənlər qovluğu "%1" mövcud deyil</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation type="unfinished">Xəta: Tənzimləmə faylını təhlil etmək mümkün deyil: %1</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">XÆta: %1</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 hələ də təhlükəsiz bağlanmayıb...</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Məbləğ</translation>
+ </message>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
@@ -227,6 +340,14 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Ayarlar faylı oxuna bilmədi</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Ayarlar faylı yazıla bilmədi</translation>
+ </message>
+ <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Ödəniş təxmin edilmədi. Fallbackfee sıradan çıxarıldı. Bir neçə blok gözləyin və ya Fallbackfee-ni fəallaşdırın.</translation>
</message>
@@ -254,17 +375,226 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<context>
<name>BitcoinGUI</name>
<message>
+ <source>&amp;Overview</source>
+ <translation type="unfinished">&amp;Ä°cmal</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation type="unfinished">Cüzdanın əsas icmalı göstərilsin</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation type="unfinished">&amp;Köçürmələr</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation type="unfinished">Köçürmə tarixçəsinə baxış</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation type="unfinished">Çı&amp;xış</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation type="unfinished">Tətbiqdən çıxış</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation type="unfinished">%1 h&amp;aqqında</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation type="unfinished">%1 haqqında məlumatlar göstərilsin</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation type="unfinished">&amp;Qt haqqında</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation type="unfinished">Qt haqqında məlumatlar göstərilsin</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation type="unfinished">%1 üçün tənzimləmə seçimlərini dəyişin</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Yeni cüzdan yaradın</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Yığın</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">Cüzdan:</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">İnternet bağlantısı söndürülüb.</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation type="unfinished">Proksi &lt;b&gt;işə salınıb&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation type="unfinished">Pulları Bitcoin ünvanına göndərin</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation type="unfinished">Cüzdanın ehtiyyat nüsxəsini başqa yerdə saxlayın</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation type="unfinished">Cüzdanın şifrələnməsi üçün istifadə olunan şifrəli sözü dəyişin</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation type="unfinished">&amp;Göndərin</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation type="unfinished">&amp;Qəbul edin</translation>
+ </message>
+ <message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;Parametrlər</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;Cüzdanı şifrələyin...</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">Cüzdanınıza aid məxfi açarları şifrələyin</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;Cüzdanın ehtiyyat nüsxəsini saxlayın...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;Şifrəli sözü dəyişin...</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">İs&amp;marıcı imzalayın...</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished">Bitcoin ünvanlarınızın sahibi olduğunuzu sübut etmək üçün ismarıcları imzalayın</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;İsmarıcı doğrulayın...</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">Göstərilmiş Bitcoin ünvanları ilə imzalandıqlarına əmin olmaq üçün ismarıcları doğrulayın</translation>
+ </message>
+ <message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">PSBT-i fayldan yük&amp;ləyin...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">&amp;URI-ni açın...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">Cüzdanı bağlayın...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">Cüzdan yaradın...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">Bütün cüzdanları bağlayın...</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation type="unfinished">&amp;Fayl</translation>
+ </message>
+ <message>
<source>&amp;Settings</source>
<translation type="unfinished">&amp;Tənzimləmələr</translation>
</message>
+ <message>
+ <source>&amp;Help</source>
+ <translation type="unfinished">&amp;Kömək</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation type="unfinished">Vərəq alətlər zolağı</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Başlıqlar eyniləşdirilir (%1%)...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">İnternet şəbəkəsi ilə eyniləşdirmə...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Bloklar diskdə indekslənir...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Bloklar diskdÉ™ icra olunur...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Bloklar diskdə təkrar indekslənir...</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">İştirakçılara qoşulur...</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation type="unfinished">Ödəmə tələbi (QR-kodlar və Bitcoin URI-ləri yaradılır):</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation type="unfinished">İstifadə olunmuş göndərmə ünvanlarının və etiketlərin siyahısını göstərmək </translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation type="unfinished">İstifadə edilmiş qəbuletmə ünvanlarının və etiketlərin siyahısını göstərmək</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation type="unfinished">Æmr &amp;sÉ™tri parametrlÉ™ri</translation>
+ </message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Köçürmə tarixçəsinin %n bloku işləndi.</numerusform>
+ <numerusform>Köçürmə tarixçəsinin %n bloku işləndi.</numerusform>
</translation>
</message>
<message>
+ <source>%1 behind</source>
+ <translation type="unfinished">%1 geridə qalır</translation>
+ </message>
+ <message>
+ <source>Catching up…</source>
+ <translation type="unfinished">Eyniləşir...</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation type="unfinished">Sonuncu qəbul edilmiş blok %1 əvvəl yaradılıb.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation type="unfinished">Bundan sonrakı köçürmələr hələlik görünməyəcək.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation type="unfinished">Xəta</translation>
</message>
@@ -277,36 +607,587 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<translation type="unfinished">Məlumat</translation>
</message>
<message>
+ <source>Up to date</source>
+ <translation type="unfinished">Eyniləşdirildi</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">Qismən imzalanmış Bitcoin köçürmələrini yükləyin</translation>
+ </message>
+ <message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">PSBT-i &amp;mübadilə yaddaşından yükləyin...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation type="unfinished">Qismən İmzalanmış Bitcoin Köçürməsini (PSBT) mübadilə yaddaşından yükləmək</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">Qovşaq pəncərəsi</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation type="unfinished">Qovşaq sazlaması və diaqnostika konsolunu açın</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished">&amp;Göndərmək üçün ünvanlar</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished">&amp;Qəbul etmək üçün ünvanlar</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation type="unfinished">Bitcoin açın: URI</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation type="unfinished">Cüzdanı açın</translation>
+ </message>
+ <message>
<source>Open a wallet</source>
<translation type="unfinished">Bir pulqabı aç</translation>
</message>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">Cüzdanı bağlayın</translation>
+ </message>
+ <message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Cüzdanı bərpa edin...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Cüzdanı ehtiyyat nüsxə faylından bərpa edin</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">Bütün cüzdanları bağlayın</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation type="unfinished">Mümkün Bitcoin əmr sətri əməliyyatları siyahısını almaq üçün %1 kömək ismarıcı göstərilsin</translation>
+ </message>
+ <message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">&amp;Dəyərləri gizlədin</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">İcmal vərəqində dəyərləri gizlədin</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">standart cüzdan</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation type="unfinished">Heç bir cüzdan yoxdur</translation>
+ </message>
+ <message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Cüzdanı verilənləri</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Cüzdan ehtiyyat nesxəsini yüklə</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Cüzdanı bərpa et</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Pulqabının adı</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;Pəncərə</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation type="unfinished">Miqyas</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation type="unfinished">Æsas pÉ™ncÉ™rÉ™</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation type="unfinished">%1 müştəri</translation>
+ </message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Gizlədin</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">&amp;Göstərin</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Bitcoin şəbəkəsinə %n aktiv bağlantı.</numerusform>
+ <numerusform>Bitcoin şəbəkəsinə %n aktiv bağlantı.</numerusform>
</translation>
</message>
- </context>
+ <message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Daha çıx əməllər üçün vurun.</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">İştirakşılar vərəqini göstərmək</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">Şəbəkə bağlantısını söndürün</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">Şəbəkə bağlantısını açın</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">XÆta: %1</translation>
+ </message>
+ <message>
+ <source>Warning: %1</source>
+ <translation type="unfinished">Xəbərdarlıq: %1</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation type="unfinished">Tarix: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation type="unfinished">Məbləğ: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation type="unfinished">Cüzdan: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation type="unfinished">Növ: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation type="unfinished">Etiket: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation type="unfinished">Ãœnvan: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation type="unfinished">Göndərilmiş köçürmə</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation type="unfinished">Daxil olan köçürmə</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation type="unfinished">HD açar yaradılması &lt;b&gt;aktivdir&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">HD açar yaradılması &lt;b&gt;söndürülüb&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">Məxfi açar &lt;b&gt;söndürülüb&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation type="unfinished">Cüzdan &lt;b&gt;şifrələnib&lt;/b&gt; və hal-hazırda &lt;b&gt;kiliddən çıxarılıb&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation type="unfinished">Cüzdan &lt;b&gt;şifrələnib&lt;/b&gt; və hal-hazırda &lt;b&gt;kiliddlənib&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Original message:</source>
+ <translation type="unfinished">Orijinal ismarıc:</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">Məbləğin vahidi. Başqa vahidi seçmək üçün vurun.</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation type="unfinished">Pul seçimi</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation type="unfinished">Miqdar:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">Baytlar:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Məbləğ:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation type="unfinished">Komissiya:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">Toz:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">Komissiydan sonra:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">Qalıq:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation type="unfinished">seçim</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation type="unfinished">AÄŸac rejimi</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation type="unfinished">Siyahı rejim</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Məbləğ</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation type="unfinished">Etiket ilə alındı</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation type="unfinished">Ünvan ilə alındı</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Tarix</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation type="unfinished">Təsdiqləmələr</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">Təsdiqləndi</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">Məbləği kopyalayın</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Ünvanı kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Etiketi kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">&amp;Məbləği kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Köçürmə &amp;İD-sini və çıxış indeksini kopyalayın</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">Xərclənməmiş qalığı &amp;kilidləyin</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">Xərclənməmiş qalığı kilidd'n &amp;çıxarın</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Miqdarı kopyalayın</translation>
</message>
<message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Komissiyanı kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Komissyadan sonra kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">Baytları koyalayın</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">Tozu kopyalayın</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation type="unfinished">Dəyişikliyi kopyalayın</translation>
</message>
<message>
+ <source>(%1 locked)</source>
+ <translation type="unfinished">(%1 kilidləndi)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation type="unfinished">bəli</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation type="unfinished">xeyr</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation type="unfinished">ÆgÉ™r alıcı mÉ™bləği cari toz hÉ™ddindÉ™n az alarsa bu etiket qırmızı olur.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation type="unfinished">Hər daxilolmada +/- %1 satoşi dəyişə bilər.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(etiket yoxdur)</translation>
</message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation type="unfinished">bunlardan qalıq: %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation type="unfinished">(qalıq)</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletActivity</name>
+ <message>
+ <source>Create Wallet</source>
+ <extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
+ <translation type="unfinished">Cüzdan yaradın</translation>
+ </message>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">&lt;b&gt;%1&lt;/b&gt; cüzdanı yaradılır...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation type="unfinished">Cüzdan yaradıla bilmədi</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation type="unfinished">Cüzdan yaradılma xəbərdarlığı</translation>
+ </message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">İmzalaynları göstərmək mümkün deyil</translation>
+ </message>
+ </context>
+<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">Cüzdanları yükləyin</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">Pulqabılar yüklənir...</translation>
+ </message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>Open wallet failed</source>
+ <translation type="unfinished">Pulqabı açıla bilmədi</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation type="unfinished">Pulqabının açılması xəbərdarlığı</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">standart cüzdan</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
+ <translation type="unfinished">Cüzdanı açın</translation>
+ </message>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">&lt;b&gt;%1&lt;/b&gt; pulqabı açılır...</translation>
+ </message>
+</context>
+<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Cüzdanı bərpa et</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">&lt;b&gt;%1&lt;/b&gt; cüzdanı bərpa olunur...</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Cüzdan bərpa oluna bilmədi</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Cüzdanın bərpa olunması xəbərdarlığı</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Cüzdanın bərpası ismarıcı</translation>
+ </message>
+</context>
+<context>
+ <name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">Cüzdanı bağlayın</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation type="unfinished">&lt;i&gt;%1&lt;/i&gt; pulqabını bağlamaq istədiyinizə əminsiniz?</translation>
+ </message>
+ <message>
+ <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
+ <translation type="unfinished">Pulqabının uzun müddət bağlı qaldıqda əgər budama (azalma) aktiv olarsa bu, bütün zəncirin təkrar eyniləşditrilməsi ilə nəticələnə bilər.</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">Bütün cüzdanları bağlayın</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation type="unfinished">Bütün pulqabılarını bağlamaq istədiyinizə əminsiniz?</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletDialog</name>
+ <message>
+ <source>Create Wallet</source>
+ <translation type="unfinished">Cüzdan yaradın</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation type="unfinished">Pulqabının adı</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation type="unfinished">Pulqabı</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation type="unfinished">Pulqabının şifrələnməsi. Pulqabı sizin seçdiyiniz şifrəli söz ilə şifrələnəcək.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation type="unfinished">Pulqabını şifrələyin</translation>
+ </message>
+ <message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">ÆlavÉ™ parametrlÉ™r</translation>
+ </message>
+ <message>
+ <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">Bu pulqabının məxfi açarını söndürün. Məxfi açarı söndürülmüş pulqabılarında məxfi açarlar saxlanılmır, onlarda HD məxfi açarlar yaradıla bilıməz və məxfi açarlar idxal edilə bilməz. Bu sadəcə müşahidə edən pulqabıları üçün ideal variantdır.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation type="unfinished">Məxfi açarları söndürün</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Boş pulqabı yaradın. Boş pulqabında ilkin olaraq açarlar və skriptlər yoxdur. Sonra məxfi açarlar və ünvanlar idxal edilə bilər və ya HD məxfi açarlar təyin edilə bilər.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation type="unfinished">Boş pulqabı yaradın</translation>
+ </message>
+ <message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation type="unfinished">Publik açar skripti (scriptPubKey) idarəetməsi üçün deskreptorlardan itifadə edin</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">Deskriptor pulqabı</translation>
+ </message>
</context>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -334,6 +1215,10 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<translation type="unfinished">&amp;UPnP istifadə edən xəritə portu</translation>
</message>
<message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;Pəncərə</translation>
+ </message>
+ <message>
<source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
<translation type="unfinished">İstifadəçi interfeys dili burada tənzimlənə bilər. Bu tənzimləmə %1 yenidən başladıldıqdan sonra təsirli olacaq.</translation>
</message>
@@ -356,10 +1241,49 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<source>&amp;Reset</source>
<translation type="unfinished">&amp;Sıfırla</translation>
</message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">Qovşaq pəncərəsi</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;Ünvanı kopyalayın</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Ünvanı kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Etiketi kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">&amp;Məbləği kopyalayın</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Məbləğ:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">Cüzdan:</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation type="unfinished">Tarix</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">Etiket</translation>
</message>
@@ -371,10 +1295,58 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<context>
<name>SendCoinsDialog</name>
<message>
+ <source>Quantity:</source>
+ <translation type="unfinished">Miqdar:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">Baytlar:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Məbləğ:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation type="unfinished">Komissiya:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">Komissiydan sonra:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">Qalıq:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">Toz:</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Miqdarı kopyalayın</translation>
</message>
<message>
+ <source>Copy amount</source>
+ <translation type="unfinished">Məbləği kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Komissiyanı kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Komissyadan sonra kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">Baytları koyalayın</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">Tozu kopyalayın</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation type="unfinished">Dəyişikliyi kopyalayın</translation>
</message>
@@ -392,6 +1364,10 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
</context>
<context>
<name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Tarix</translation>
+ </message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
@@ -399,10 +1375,18 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<numerusform />
</translation>
</message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Məbləğ</translation>
+ </message>
</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation type="unfinished">Tarix</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">Etiket</translation>
</message>
@@ -418,6 +1402,31 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<translation type="unfinished">BaÅŸqa</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Ünvanı kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Etiketi kopyalayın</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">&amp;Məbləği kopyalayın</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Vergüllə ayrılmış fayl</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">Təsdiqləndi</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Tarix</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">Etiket</translation>
</message>
@@ -433,11 +1442,22 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<context>
<name>WalletFrame</name>
<message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Yeni cüzdan yaradın</translation>
+ </message>
+ <message>
<source>Error</source>
<translation type="unfinished">Xəta</translation>
</message>
</context>
<context>
+ <name>WalletModel</name>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">standart cüzdan</translation>
+ </message>
+</context>
+<context>
<name>WalletView</name>
<message>
<source>&amp;Export</source>
@@ -447,5 +1467,10 @@ Daxil olma, yalnız 'qanuni' tipli ünvanlar ilə mümkündür.</translation>
<source>Export the data in the current tab to a file</source>
<translation type="unfinished">Hazırki vərəqdəki verilənləri fayla ixrac edin</translation>
</message>
+ <message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Cüzdanı verilənləri</translation>
+ </message>
</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_be.ts b/src/qt/locale/bitcoin_be.ts
index 8fa9499138..d242a54544 100644
--- a/src/qt/locale/bitcoin_be.ts
+++ b/src/qt/locale/bitcoin_be.ts
@@ -660,6 +660,30 @@
<translation type="unfinished">Біткойн</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -903,15 +927,7 @@
<source>Message:</source>
<translation type="unfinished">Паведамленне:</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Заплаціць да:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">ПамÑтка:</translation>
- </message>
-</context>
+ </context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
@@ -923,10 +939,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/непацверджана</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 пацверджаннÑÑž</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts
index eeaabd47c2..4b3b3d44de 100644
--- a/src/qt/locale/bitcoin_bg.ts
+++ b/src/qt/locale/bitcoin_bg.ts
@@ -87,6 +87,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ИзнеÑи лиÑÑ‚ Ñ Ð°Ð´Ñ€ÐµÑи</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Файл, разделен ÑÑŠÑ Ð·Ð°Ð¿ÐµÑ‚Ð°Ñ</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">Получи Ñе грешка при запазването на лиÑта Ñ Ð°Ð´Ñ€ÐµÑи към %1. ÐœÐ¾Ð»Ñ Ð¾Ð¿Ð¸Ñ‚Ð°Ð¹Ñ‚Ðµ пак.</translation>
@@ -174,6 +179,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Въведете Ñтарата и новата паролна фраза за портфейла.</translation>
</message>
<message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation type="unfinished">Ðе забравÑйте, че криптирането на Ð²Ð°ÑˆÐ¸Ñ Ð¿Ð¾Ñ€Ñ‚Ñ„ÐµÐ¹Ð» не може напълно да защити вашите биткойни от кражба от зловреден Ñофтуер, заразÑващ компютъра ви.</translation>
+ </message>
+ <message>
<source>Wallet to be encrypted</source>
<translation type="unfinished">Портфейл за криптиране</translation>
</message>
@@ -232,6 +241,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Файлът Ñ Ð½Ð°Ñтройки %1 може да е повреден или невалиден.</translation>
+ </message>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">Изключи бÑгащите</translation>
+ </message>
+ <message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
<translation type="unfinished">Фатална грешка Ñе поÑви. %1 не може да продължи безопаÑтно и ще Ñе затвори.</translation>
</message>
@@ -239,7 +256,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Internal error</source>
<translation type="unfinished">Вътрешна грешка.</translation>
</message>
- </context>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">Възникна вътрешна грешка. %1 ще Ñе опита да продължи безопаÑно. Това е неочакван бъг, който може да бъде докладван, както е опиÑано по-долу.</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
@@ -257,6 +278,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Грешка:Избраната "%1" Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ðµ ÑъщеÑтвува.</translation>
</message>
<message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation type="unfinished">Грешка: Ðе може да Ñе анализира ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»: %1.</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Грешка: %1</translation>
</message>
@@ -439,7 +464,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Transaction too large</source>
<translation type="unfinished">ТранзакциÑта е твърде голÑма</translation>
</message>
- </context>
+ <message>
+ <source>Unknown new rules activated (versionbit %i)</source>
+ <translation type="unfinished">Ðктивирани Ñа неизвеÑтни нови правила (versionbit %i)</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Ðеподдържана logging категориÑ%s=%s.</translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation type="unfinished">Коментар потребителÑки агент (%s) Ñъдържа не безопаÑни знаци. </translation>
+ </message>
+ <message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">Секторите Ñе проверÑват...</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)…</source>
+ <translation type="unfinished">Потвърждаване на портфейл(и)...</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation type="unfinished">Портфейлът Ñ‚Ñ€Ñбва да бъде презапиÑан : реÑтартирай %s , за да завърши</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
@@ -568,6 +617,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Зареди PSBT от файл…</translation>
</message>
<message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">Отвори &amp;URI...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">Затвори Портфейл...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">Създай Портфейл...</translation>
+ </message>
+ <message>
<source>Close All Wallets…</source>
<translation type="unfinished">Затвори вÑички уолети</translation>
</message>
@@ -588,10 +649,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Лентата Ñ Ð¸Ð½Ñтрументи</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Синхронизиране на хедъри (%1%)</translation>
+ </message>
+ <message>
<source>Synchronizing with network…</source>
<translation type="unfinished">Синхронизиране Ñ Ð¼Ñ€ÐµÐ¶Ð°</translation>
</message>
<message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">ИндекÑиране на блокове от диÑка...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Обработват Ñе блокове на диÑка...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">ПреиндекÑиране на блоково от диÑка...</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">Свързване Ñ Ñ€Ð¾Ñк...</translation>
+ </message>
+ <message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished">ИзиÑкване на плащаниÑ(генерира QR кодове и биткойн: URIs)</translation>
</message>
@@ -619,6 +700,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1 зад</translation>
</message>
<message>
+ <source>Catching up…</source>
+ <translation type="unfinished">ÐавакÑвам...</translation>
+ </message>
+ <message>
<source>Last received block was generated %1 ago.</source>
<translation type="unfinished">ПоÑÐ»ÐµÐ´Ð½Ð¸Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½ блок е генериран преди %1.</translation>
</message>
@@ -643,10 +728,42 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðктуално</translation>
</message>
<message>
+ <source>Ctrl+Q</source>
+ <translation type="unfinished">Ctrl+Q </translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">Заредете чаÑтично подпиÑана Bitcoin транÑакциÑ</translation>
+ </message>
+ <message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">Заредете PSBT (чаÑтично подпиÑана Bitcoin транÑакциÑ) от &amp;клипборд...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation type="unfinished">Заредете чаÑтично подпиÑана Bitcoin транÑÐ°ÐºÑ†Ð¸Ñ Ð¾Ñ‚ клипборд</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation type="unfinished">Прозорец на възела</translation>
</message>
<message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation type="unfinished">Отвори конзола за отÑтранÑване на грешки и диагноÑтика на възела</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished">&amp;Изпращане на адреÑи</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished">&amp;Получаване на адреÑи</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation type="unfinished">Отвори bitcoin: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation type="unfinished">Отворете портфейл</translation>
</message>
@@ -659,6 +776,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Затвори портфейла</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">ВъзÑтановÑване на Портфейл...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">ВъзÑтанови портфейла от резервен файл</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Затвори вÑички портфейли</translation>
</message>
@@ -667,6 +794,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Покажи %1 помощно Ñъобщение за да получиш лиÑÑ‚ Ñ Ð²ÑŠÐ·Ð¼Ð¾Ð¶Ð½Ð¸ Биткойн команди</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">§МаÑкирай ÑтойноÑтите</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">МаÑкирай ÑтойноÑтите в раздела Преглед</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">Портфейл по подразбиране</translation>
</message>
@@ -675,10 +810,34 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ÐÑма доÑтъпни портфейли</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Данни от портфейла</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Зареди резервно копие на портфейл</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">ВъзÑтановÑване на Портфейл</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Име на портфейл</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Прозорец</translation>
</message>
<message>
+ <source>Ctrl+M</source>
+ <translation type="unfinished">Ctrl+M </translation>
+ </message>
+ <message>
<source>Zoom</source>
<translation type="unfinished">Увеличи</translation>
</message>
@@ -690,6 +849,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 клиент</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Скрий</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">&amp;Покажи</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -704,6 +871,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Клик за повече дейÑтвиÑ</translation>
</message>
<message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">Показване на раздела Ñ ÐŸÐ¸ÑŠÑ€Ð¸</translation>
+ </message>
+ <message>
<source>Disable network activity</source>
<extracomment>A context menu item.</extracomment>
<translation type="unfinished">Блокирай мрежова активноÑÑ‚</translation>
@@ -791,6 +963,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">Елемент за показване на Ñуми. Щракнете, за да изберете друга единица.</translation>
+ </message>
+</context>
+<context>
<name>CoinControlDialog</name>
<message>
<source>Coin Selection</source>
@@ -869,10 +1048,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Копирай адреÑ</translation>
</message>
<message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копиране на етикет</translation>
+ </message>
+ <message>
<source>Copy &amp;amount</source>
<translation type="unfinished">Копирай Ñума</translation>
</message>
<message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Копирайте идентификатора &amp;ID на транÑакциÑта и Ð¸Ð·Ñ…Ð¾Ð´Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑ</translation>
+ </message>
+ <message>
<source>L&amp;ock unspent</source>
<translation type="unfinished">Заключи неизхарчено</translation>
</message>
@@ -953,7 +1140,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Create wallet failed</source>
<translation type="unfinished">Създаването на портфейл не бе уÑпешен</translation>
</message>
- </context>
+ <message>
+ <source>Create wallet warning</source>
+ <translation type="unfinished">Създайте предупредителен портфейл </translation>
+ </message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Ðе мога да Ð¸Ð·Ð±Ñ€Ð¾Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñите</translation>
+ </message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Ðамерени Ñа твърде много външни подпиÑващи</translation>
+ </message>
+</context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -974,6 +1173,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ОтварÑнето на уолет неупÑешно</translation>
</message>
<message>
+ <source>Open wallet warning</source>
+ <translation type="unfinished">Внимание, отворен портфейл</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">Портфейл по подразбиране</translation>
</message>
@@ -982,7 +1185,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">Отворете портфейл</translation>
</message>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">ОтварÑне на портфейл &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+</context>
+<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">ВъзÑтановÑване на Портфейл</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">ВъзÑтановÑването на портфейла не бе уÑпешно</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Съобщение портфейлът е възÑтановен</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
@@ -990,10 +1216,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Затвори портфейла</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation type="unfinished">Сигурни ли Ñте, че иÑкате да затворите портфейла&lt;i&gt;%1&lt;/i&gt;?</translation>
+ </message>
+ <message>
+ <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
+ <translation type="unfinished">ЗатварÑнето на портфейла за твърде дълго може да доведе до необходимоÑÑ‚ от повторно Ñинхронизиране на цÑлата верига, ако Ñъкращаването е активирано.</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Затвори вÑички портфейли</translation>
</message>
- </context>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation type="unfinished">Сигурни ли Ñте, че иÑкате да затворите вÑички портфейли?</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
<message>
@@ -1009,14 +1247,63 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">портфейл</translation>
</message>
<message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation type="unfinished">Кодиране на портфейла. Портфейлът ще бъде криптиран Ñ Ð¿Ð°Ñ€Ð¾Ð»Ð° по ваш избор.</translation>
+ </message>
+ <message>
<source>Encrypt Wallet</source>
<translation type="unfinished">Криптирай портфейла</translation>
</message>
<message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">Разширени наÑтройки</translation>
+ </message>
+ <message>
+ <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">Деактивирайте чаÑтните ключове за този портфейл. Портфейлите Ñ Ð´ÐµÐ°ÐºÑ‚Ð¸Ð²Ð¸Ñ€Ð°Ð½Ð¸ чаÑтни ключове нÑма да имат чаÑтни ключове и не могат да имат HD seed или импортирани чаÑтни ключове. Това е идеално за портфейли, които Ñлужат Ñамо за наблюдение на баланÑа.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation type="unfinished">Изключете чаÑтните (тайните) ключове</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Създайте празен портфейл. Празните портфейли първоначално нÑмат чаÑтни ключове или Ñкриптове. ЧаÑтните ключове и адреÑи могат да бъдат импортирани или може да Ñе зададе HD seed по-къÑно. </translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation type="unfinished">Създайте празен портфейл</translation>
+ </message>
+ <message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation type="unfinished">Използвайте декодери за управление на scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">Декодер за портфейл</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">Външен подпиÑ</translation>
+ </message>
+ <message>
<source>Create</source>
<translation type="unfinished">Създай</translation>
</message>
- </context>
+ <message>
+ <source>Compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished">Компилиран без поддръжка на sqlite (изиÑква Ñе за декодер на портфейли)</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Компилиран без поддръжка на външни подпиÑи (изиÑква Ñе за външно подпиÑване)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -1056,6 +1343,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">"%1" не е валиден Биткоин адреÑ.</translation>
</message>
<message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation type="unfinished">ÐдреÑÑŠÑ‚ "%1" вече ÑъщеÑтвува като Ð°Ð´Ñ€ÐµÑ Ð·Ð° получаване Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚ "%2" и затова не може да бъде добавен като Ð°Ð´Ñ€ÐµÑ Ð·Ð° изпращане.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation type="unfinished">ВъведениÑÑ‚ Ð°Ð´Ñ€ÐµÑ "%1" вече е в адреÑната книга Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚ "%2".</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">Ðе може да отключите портфейла.</translation>
</message>
@@ -1093,6 +1388,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Bitcoin</source>
<translation type="unfinished">Биткоин</translation>
</message>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Ðай малко %1 GB данни ще бъдат запаметени в тази директориÑ, и ще нараÑтват през времето.</translation>
@@ -1114,6 +1430,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1 ще Ñвали и Ñъхрани копие на биткойн блокчейна.</translation>
</message>
<message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation type="unfinished">Портфейлът ще Ñе ÑъхранÑва и в тази директориÑ.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation type="unfinished">Грешка: Ðе може да Ñе Ñъздаде поÑочената Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð·Ð° данни "%1"</translation>
+ </message>
+ <message>
<source>Error</source>
<translation type="unfinished">грешка</translation>
</message>
@@ -1130,10 +1454,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Програмата Ñе Ñтартира за първи път вие може да изберете къде %1 ще Ñе запаметÑÑ‚ данните.</translation>
</message>
<message>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">Ограничете блокчейнното Ñъхранение</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Връщането на тази наÑтройка изиÑква повторно изтеглÑне на цÑлата Ñекторна верига. По-бързо е първо да изтеглите пълната верига и да Ñ Ð¿Ð¾Ð´Ñ€Ñзвате по-къÑно. Деактивира нÑкои разширени функции.</translation>
+ </message>
+ <message>
+ <source> GB</source>
+ <translation type="unfinished">ГБ</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">Първоначалната ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ðµ изключително взиÑкателна, и може да разкрие хардуерни проблеми Ñ Ð²Ð°ÑˆÐ¸Ñ ÐºÐ¾Ð¼Ð¿ÑŽÑ‚ÑŠÑ€, които до Ñега Ñа били незабелÑзани. Ð’Ñеки път, когато включите %1, ÑвалÑнето ще започне от където е приключило.</translation>
</message>
<message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation type="unfinished">Ðко Ñте избрали да ограничите Ñъхранението на блокови вериги (подрÑзване), иÑторичеÑките данни вÑе още Ñ‚Ñ€Ñбва да бъдат изтеглени и обработени, но ще бъдат изтрити Ñлед това, за да поддържате използването на Ð²Ð°ÑˆÐ¸Ñ Ð´Ð¸Ñк.</translation>
+ </message>
+ <message>
<source>Use the default data directory</source>
<translation type="unfinished">Използване на Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð¿Ð¾ подразбиране</translation>
</message>
@@ -1160,6 +1500,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1 изключва Ñе...</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation type="unfinished">Ðе изключвайте компютъра докато този прозорец не изчезне.</translation>
</message>
@@ -1171,6 +1515,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">форма</translation>
</message>
<message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation type="unfinished">ПоÑледните транÑакции вÑе още не могат да Ñе виждат и Ñледователно баланÑÑŠÑ‚ на портфейла ви може да бъде неправилен. Тази Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‰Ðµ бъде правилна, Ñлед като портфейлът ви приключи Ñинхронизирането Ñ Bitcoin мрежата, както е подробно опиÑано по-долу.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation type="unfinished">Опитът да Ñе изразходват биткойни, които Ñа заÑегнати от вÑе още показаните транÑакции, нÑма да бъдат приети от мрежата.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation type="unfinished">Брой оÑтанали блокове</translation>
+ </message>
+ <message>
+ <source>Unknown…</source>
+ <translation type="unfinished">ÐеизвеÑтно...</translation>
+ </message>
+ <message>
+ <source>calculating…</source>
+ <translation type="unfinished">изчиÑлÑване...</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation type="unfinished">Време на поÑÐ»ÐµÐ´Ð½Ð¸Ñ Ð±Ð»Ð¾Ðº</translation>
</message>
@@ -1179,13 +1543,37 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">прогреÑ</translation>
</message>
<message>
+ <source>Progress increase per hour</source>
+ <translation type="unfinished">Увеличаване на напредъка на чаÑ</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation type="unfinished">Прогнозираното време оÑтава до Ñинхронизиране</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation type="unfinished">Скрий</translation>
</message>
+ <message>
+ <source>Esc</source>
+ <translation type="unfinished">избÑгай</translation>
+ </message>
+ <message>
+ <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
+ <translation type="unfinished">%1 в момента Ñинхронизира. Той ще Ð¸Ð·Ñ‚ÐµÐ³Ð»Ñ Ð·Ð°Ð³Ð»Ð°Ð²Ð¸Ñ Ð¸ блокове от роÑка и ще ги утвърди, докато доÑтигне върха на Ñекторната верига.</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">ÐеизвеÑтно. Синхронизиране на Глави (%1, %2%)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
+ <source>Open bitcoin URI</source>
+ <translation type="unfinished">Отвори bitcoin URI </translation>
+ </message>
+ <message>
<source>Paste address from clipboard</source>
<extracomment>Tooltip text for button that allows you to paste an address that is in your clipboard.</extracomment>
<translation type="unfinished">Вмъкни от клипборда</translation>
@@ -1202,6 +1590,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;ОÑновни</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation type="unfinished">Ðвтоматично Ñтартиране %1 Ñлед влизане в ÑиÑтемата.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation type="unfinished">&amp;Стартиране %1 при влизане в ÑиÑтемата</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Ðктивирането на подрÑзването значително намалÑва диÑковото проÑтранÑтво, необходимо за ÑъхранÑване на транÑакции. Ð’Ñички блокове вÑе още Ñа напълно валидирани. Връщането на тази наÑтройка изиÑква повторно изтеглÑне на Ñ†ÐµÐ»Ð¸Ñ Ð±Ð»Ð¾ÐºÑ‡ÐµÐ¹Ð½.</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation type="unfinished">Размер на кеша в &amp;базата данни</translation>
</message>
@@ -1214,6 +1614,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">IP Ð°Ð´Ñ€ÐµÑ Ð½Ð° прокÑи (напр. за IPv4: 127.0.0.1 / за IPv6: ::1)</translation>
</message>
<message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation type="unfinished">Показва дали предоÑтавениÑÑ‚ proxy по подразбиране Socks5 Ñе използва за доÑтигане до роÑк чрез този тип мрежа.</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Минимизиране вмеÑто излизане от приложението, когато прозорецът е затворен. Когато тази Ð¾Ð¿Ñ†Ð¸Ñ Ðµ активирана, приложението ще Ñе затвори Ñамо Ñлед избиране на Изход от менюто.</translation>
+ </message>
+ <message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Опциите, зададени в този диалогов прозорец, Ñе заменÑÑ‚ от ÐºÐ¾Ð¼Ð°Ð½Ð´Ð½Ð¸Ñ Ñ€ÐµÐ´:</translation>
+ </message>
+ <message>
<source>Open Configuration File</source>
<translation type="unfinished">Отворете ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð»</translation>
</message>
@@ -1230,14 +1642,56 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Мрежа</translation>
</message>
<message>
+ <source>Prune &amp;block storage to</source>
+ <translation type="unfinished">Съкратете &amp;блоковото хранилище до</translation>
+ </message>
+ <message>
<source>GB</source>
<translation type="unfinished">ГБ</translation>
</message>
<message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation type="unfinished">Връщането на тази наÑтройка изиÑква повторно изтеглÑне на цÑлата блокова верига.</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">МакÑимален размер кеш за базата данни. По-големиÑÑ‚ кеш може да допринеÑе за по-бърза ÑинхронизациÑ, Ñлед което ползата е по-малко изразена за повечето Ñлучаи на употреба. ÐамалÑването на размера на кеша ще намали използването на паметта. Ðеизползваната mempool памет Ñе ÑÐ¿Ð¾Ð´ÐµÐ»Ñ Ð·Ð° този кеш.</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Задайте Ð±Ñ€Ð¾Ñ Ð½Ð° нишките за проверка на Ñкрипта. Отрицателните ÑтойноÑти ÑъответÑтват на Ð±Ñ€Ð¾Ñ Ñдра, които иÑкате да оÑтавите Ñвободни за ÑиÑтемата.</translation>
+ </message>
+ <message>
+ <source>(0 = auto, &lt;0 = leave that many cores free)</source>
+ <translation type="unfinished">(0 = авто, &lt;0 = оÑтавете толкова Ñвободни Ñдра) </translation>
+ </message>
+ <message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Това позволÑва на Ð²Ð°Ñ Ð¸Ð»Ð¸ на инÑтрумент на трета Ñтрана да комуникирате Ñ Ð²ÑŠÐ·ÐµÐ»Ð° чрез команден ред и JSON-RPC команди.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">Ðктивиране на R&amp;PC Ñървър</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">По&amp;ртфейл</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Дали да зададете изваждане на такÑа от Ñумата по подразбиране или не.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Изваждане &amp;такÑа от Ñума по подразбиране</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">ЕкÑперт</translation>
</message>
@@ -1246,10 +1700,36 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ПозволÑване на монетите и &amp;техните възможноÑти</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Ðко деактивирате разходите за непотвърдена промÑна, промÑната от транÑÐ°ÐºÑ†Ð¸Ñ Ð½Ðµ може да Ñе използва, докато тази Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ Ð½Ñма поне едно потвърждение. Това Ñе отразÑва и на това как Ñе изчиÑлÑва вашиÑÑ‚ баланÑ.</translation>
+ </message>
+ <message>
<source>&amp;Spend unconfirmed change</source>
<translation type="unfinished">&amp;Похарчете непотвърденото реÑто</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Ðктивиране &amp;PSBT контроли</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Дали да покажа PSBT контроли.</translation>
+ </message>
+ <message>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">Външен Ð¿Ð¾Ð´Ð¿Ð¸Ñ (например хардуерен портфейл)</translation>
+ </message>
+ <message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">&amp;Външен път на Ñкрипта на подпиÑващиÑ</translation>
+ </message>
+ <message>
+ <source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
+ <translation type="unfinished">Пълен път към ÑъвмеÑтим Ñ Ð±Ð¸Ñ‚ÐºÐ¾Ð¹Ð½ оÑновен Ñкрипт (например C: \ Downloads \ hwi.exe или /users/you/downloads/hwi.py). Внимавайте: злонамерен Ñофтуер може да открадне вашите монети!</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">Ðвтоматично отварÑне на входÑÑ‰Ð¸Ñ Bitcoin порт. Работи Ñамо Ñ Ñ€ÑƒÑ‚ÐµÑ€Ð¸ поддържащи UPnP.</translation>
</message>
@@ -1326,6 +1806,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Дали да покаже възможноÑтите за контрол на монетите или не.</translation>
</message>
<message>
+ <source>Monospaced font in the Overview tab:</source>
+ <translation type="unfinished">Моноширинен шрифт в раздела Общ преглед:</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation type="unfinished">ОК</translation>
</message>
@@ -1334,6 +1818,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Отказ</translation>
</message>
<message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Компилиран без поддръжка на външни подпиÑи (изиÑква Ñе за външно подпиÑване)</translation>
+ </message>
+ <message>
<source>default</source>
<translation type="unfinished">подразбиране</translation>
</message>
@@ -1343,14 +1832,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Потвърдете опциите за нулиране</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">ИзиÑква Ñе реÑтартиране на клиента за активиране на извършените промени.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Клиентът ще бъде изключен. ИÑкате ли да продължите?</translation>
</message>
<message>
@@ -1429,6 +1921,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>PSBTOperationsDialog</name>
<message>
+ <source>Save…</source>
+ <translation type="unfinished">Запази...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation type="unfinished">Затвори</translation>
+ </message>
+ <message>
<source>or</source>
<translation type="unfinished">или</translation>
</message>
@@ -1751,6 +2251,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Копирай адреÑ</translation>
</message>
<message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копиране на етикет</translation>
+ </message>
+ <message>
<source>Copy &amp;amount</source>
<translation type="unfinished">Копирай Ñума</translation>
</message>
@@ -1971,10 +2475,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Transaction creation failed!</source>
<translation type="unfinished">Грешка при Ñъздаването на транзакциÑ!</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">ЗаÑвката за плащане е изтекла.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2029,15 +2529,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Message:</source>
<translation type="unfinished">Съобщение:</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Плащане на:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Бележка:</translation>
- </message>
-</context>
+ </context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
@@ -2148,15 +2640,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>TransactionDesc</name>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/непотвърдено, %1</translation>
- </message>
- <message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/непотвърдени</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">включена в %1 блока</translation>
</message>
<message>
@@ -2412,6 +2902,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Копирай адреÑ</translation>
</message>
<message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копиране на етикет</translation>
+ </message>
+ <message>
<source>Copy &amp;amount</source>
<translation type="unfinished">Копирай Ñума</translation>
</message>
@@ -2420,6 +2914,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ИзнаÑÑне иÑториÑта на транзакциите</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Файл, разделен ÑÑŠÑ Ð·Ð°Ð¿ÐµÑ‚Ð°Ñ</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">Потвърдено</translation>
</message>
@@ -2509,6 +3008,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Запазване на портфейла</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Данни от портфейла</translation>
+ </message>
+ <message>
<source>Backup Failed</source>
<translation type="unfinished">ÐеуÑпешно запазване на портфейла</translation>
</message>
diff --git a/src/qt/locale/bitcoin_bn.ts b/src/qt/locale/bitcoin_bn.ts
index b76dbb3bee..2403069575 100644
--- a/src/qt/locale/bitcoin_bn.ts
+++ b/src/qt/locale/bitcoin_bn.ts
@@ -55,6 +55,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">1%1 সেটিংস ফাইল টি সমà§à¦­à¦¬à¦¤ নষà§à¦Ÿ বা করাপà§à¦Ÿ</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">পলাতক বà§à¦¯à¦¤à¦¿à¦•à§à¦°à¦®</translation>
</message>
@@ -74,6 +78,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">আপনি কি সেটিংস পà§à¦¨à¦°à¦¾à¦¯à¦¼ ডিফলà§à¦Ÿ করতে,অথবা কোনো পরিবরà§à¦¤à¦¨ ছাড়াই ফিরে যেতে চান? </translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">à¦à¦•à¦Ÿà¦¿ জটিল তà§à¦°à§à¦Ÿà¦¿ হয়েছে। সেটিং ফাইল টি রাইটেবল কিনা চেক করà§à¦¨, অথবা -nosettings দিয়ে রান করার চেষà§à¦Ÿà¦¾ করà§à¦¨</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely…</source>
<translation type="unfinished">%1 à¦à¦–নো নিরাপদে বের হয়নি</translation>
</message>
@@ -268,10 +282,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>WalletController</name>
<message>
- <source>Close wallet</source>
- <translation type="unfinished">ওয়ালেট বনà§à¦§ করà§à¦¨</translation>
- </message>
- <message>
<source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
<translation type="unfinished">আপনি কি নিশà§à¦šà¦¿à¦¤ যে আপনি ওয়ালেট বনà§à¦§ করতে চান&lt;i&gt;%1&lt;/i&gt;?</translation>
</message>
@@ -311,6 +321,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -322,11 +353,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>PeerTableModel</name>
<message>
- <source>Address</source>
- <extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
- <translation type="unfinished">ঠিকানা</translation>
- </message>
- <message>
<source>Type</source>
<extracomment>Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</extracomment>
<translation type="unfinished">টাইপ</translation>
@@ -370,10 +396,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Date</source>
<translation type="unfinished">তারিখ</translation>
</message>
- <message>
- <source>Label</source>
- <translation type="unfinished">লেবেল</translation>
- </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -416,10 +438,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Type</source>
<translation type="unfinished">টাইপ</translation>
</message>
- <message>
- <source>Label</source>
- <translation type="unfinished">লেবেল</translation>
- </message>
</context>
<context>
<name>TransactionView</name>
@@ -445,14 +463,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">টাইপ</translation>
</message>
<message>
- <source>Label</source>
- <translation type="unfinished">লেবেল</translation>
- </message>
- <message>
- <source>Address</source>
- <translation type="unfinished">ঠিকানা</translation>
- </message>
- <message>
<source>ID</source>
<translation type="unfinished">আইডি</translation>
</message>
diff --git a/src/qt/locale/bitcoin_bs.ts b/src/qt/locale/bitcoin_bs.ts
index f0268f6ade..2fe0dd8359 100644
--- a/src/qt/locale/bitcoin_bs.ts
+++ b/src/qt/locale/bitcoin_bs.ts
@@ -487,10 +487,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nepodržana kategorija logivanja %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Nadogradnja UTXO baze podataka</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Komentar korisniÄkog agenta (%s) sadrži nesigurne znakove.</translation>
</message>
@@ -767,6 +763,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nema dostupnih novÄanika</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Ime NovÄanika</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Prozor</translation>
</message>
@@ -1182,6 +1183,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Najmanje %1 GB podataka bit će pohranjeno u ovom direktoriju i vremenom će rasti.</translation>
@@ -1228,10 +1253,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Zato Å¡to je ovo prvi put da se program pokreće, možete odabrati gdje će %1 Äuvati svoje podatke.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Kada kliknete OK, %1 će poÄeti preuzimati i obraÄ‘ivati ​​puni lanac blokova %4 (%2GB), poÄevÅ¡i od najranijih transakcija u %3 kada je %4 prvi put pokrenut.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">Vraćanje ove postavke zahtijeva ponovno preuzimanje cijelog lanca blokova. Brže je prvo preuzeti Äitav lanac i kasnije ga obrezati. Onemogućava neke napredne funkcije.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts
index 22a5ab2ca3..8a7d4eb8dd 100644
--- a/src/qt/locale/bitcoin_ca.ts
+++ b/src/qt/locale/bitcoin_ca.ts
@@ -257,14 +257,20 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<source>Internal error</source>
<translation type="unfinished">Error intern</translation>
</message>
- <message>
- <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <translation type="unfinished">S'ha produït un error intern. %1 intentarà continuar amb seguretat. Es pot informar sobre aquest error inesperat com es descriu a continuació.</translation>
- </message>
-</context>
+ </context>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Voleu restablir la configuració als valors predeterminats o sortir sense desar els canvis?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Un error fatal s'ha produit. Revisa que l'arxiu de preferències sigui d'escriptura, o torna-ho a intentar amb -nosettings</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Error: El directori de dades especificat «%1» no existeix.</translation>
</message>
@@ -384,6 +390,14 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">El fitxer de configuració no es pot llegir</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">El fitxer de configuració no pot ser escrit</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">Els desenvolupadors %s</translation>
</message>
@@ -432,10 +446,6 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<translation type="unfinished">Error: les carteres heretades només admeten els tipus d'adreces «legacy», «p2sh-segwit» i «bech32»</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Error: ha fallat escoltar les connexions entrants (l'escoltament ha retornat l'error %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">L'estimació de la quota ha fallat. Fallbackfee està desactivat. Espereu uns quants blocs o activeu -fallbackfee.</translation>
</message>
@@ -644,10 +654,6 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<translation type="unfinished">S'ha produït un error en llegir el següent registre de la base de dades de la cartera</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">S'ha produït un error en actualitzar la base de dades de chainstate</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Error: No s'ha pogut crear el cursor a la base de dades</translation>
</message>
@@ -781,10 +787,6 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<translation type="unfinished">Cal especificar un port amb -whitebind: «%s»</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">No s'ha especificat cap servidor intermediari. Utilitzeu -proxy =&lt;ip&gt; o -proxy =&lt;ip:port&gt;.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">No hi ha suficient descriptors de fitxers disponibles.</translation>
</message>
@@ -793,10 +795,6 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<translation type="unfinished">La poda no es pot configurar amb un valor negatiu.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">El mode de poda és incompatible amb -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">El mode de poda és incompatible amb -txindex.</translation>
</message>
@@ -961,10 +959,6 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<translation type="unfinished">Categoria de registre no admesa %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Actualització de la base de dades UTXO</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">El comentari de l'agent d'usuari (%s) conté caràcters insegurs.</translation>
</message>
@@ -1032,6 +1026,10 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<translation type="unfinished">Crear una nova cartera</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Minimitza</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Moneder:</translation>
</message>
@@ -1090,7 +1088,7 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Signa els missatges amb la seva adreça de Bitcoin per a provar que les posseeixes</translation>
+ <translation type="unfinished">Signa el missatges amb la seva adreça de Bitcoin per provar que les poseeixes</translation>
</message>
<message>
<source>&amp;Verify message…</source>
@@ -1098,7 +1096,7 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation type="unfinished">Verifiqueu els missatges per a assegurar-vos que han estat signats amb una adreça Bitcoin específica.</translation>
+ <translation type="unfinished">Verifiqueu els missatges per assegurar-vos que han estat signats amb una adreça Bitcoin específica.</translation>
</message>
<message>
<source>&amp;Load PSBT from file…</source>
@@ -1216,6 +1214,10 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<translation type="unfinished">Carrega la transacció Bitcoin signada parcialment</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">Carrega la PSBT des del porta-retalls.</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Carrega la transacció de Bitcoin signada parcialment des del porta-retalls</translation>
</message>
@@ -1276,6 +1278,16 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<translation type="unfinished">No hi ha cap cartera disponible</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Dades de la cartera</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nom de la cartera</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Finestra</translation>
</message>
@@ -1291,6 +1303,10 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<source>%1 client</source>
<translation type="unfinished">Client de %1</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Amaga</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1570,7 +1586,7 @@ Només és possible firmar amb adreces del tipus "legacy".</translation>
<source>Can't list signers</source>
<translation type="unfinished">No es poden enumerar signants</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenWalletActivity</name>
<message>
@@ -1772,13 +1788,26 @@ Això és ideal per a carteres de mode només lectura.</translation>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(of %1 GB necessaris)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB necessaris per a la cadena completa)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1821,10 +1850,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation type="unfinished">Com és la primera vegada que s'executa el programa, podeu triar on %1 emmagatzemaran les dades.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Quan feu clic a D'acord, %1 començarà a descarregar i processar la cadena de blocs %4 completa (%2 GB) començant per les primeres transaccions de %3, any de llençament inicial de %4.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Limita l’emmagatzematge de la cadena de blocs a</translation>
</message>
@@ -1929,7 +1954,7 @@ Això és ideal per a carteres de mode només lectura.</translation>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Desconegut. Sincronització de les capçaleres (%1, %2%)...</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2157,10 +2182,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation type="unfinished">coincidència més propera "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Opcions configurades en aquest diàleg són sobreescrites per la línia de comandes o el fitxer de configuració:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;D'acord</translation>
</message>
@@ -2183,14 +2204,17 @@ Això és ideal per a carteres de mode només lectura.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirmeu el reestabliment de les opcions</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Cal reiniciar el client per a activar els canvis.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">S'aturarà el client. Voleu procedir?</translation>
</message>
<message>
@@ -3410,10 +3434,6 @@ Nota: atès que la tarifa es calcula per byte, una tarifa de "100 satoshis per k
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Una tarifa superior a %1 es considera una tarifa absurdament alta.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">La sol·licitud de pagament ha vençut.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3497,14 +3517,6 @@ Nota: atès que la tarifa es calcula per byte, una tarifa de "100 satoshis per k
<translation type="unfinished">Missatge:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Aquesta és una sol·licitud de pagament no autenticada.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Aquesta és una sol·licitud de pagament autenticada.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduïu una etiqueta per a aquesta adreça per afegir-la a la llista d'adreces utilitzades</translation>
</message>
@@ -3512,11 +3524,7 @@ Nota: atès que la tarifa es calcula per byte, una tarifa de "100 satoshis per k
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Un missatge que s'ha adjuntat al bitcoin: URI que s'emmagatzemarà amb la transacció per a la vostra referència. Nota: el missatge no s'enviarà a través de la xarxa Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Paga a:</translation>
- </message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -3686,30 +3694,22 @@ Nota: atès que la tarifa es calcula per byte, una tarifa de "100 satoshis per k
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">produït un conflicte amb una transacció amb %1 confirmacions</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/no confirmades, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">a la reserva de memòria</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">no a la reserva de memòria</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abandonada</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/sense confirmar</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 confirmacions</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts
index 497d17b022..9762ef7c84 100644
--- a/src/qt/locale/bitcoin_cs.ts
+++ b/src/qt/locale/bitcoin_cs.ts
@@ -241,6 +241,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Soubor s nastavením %1 může být poškozený nebo neplatný.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Uprchlá výjimka</translation>
</message>
@@ -260,6 +264,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Přeješ si obnovit výchozí nastavení, nebo odejít bez ukládání změn?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Nastala závažná chyba. Ověř zda-li je možné do souboru s nastavením zapisovat a nebo vyzkoušej aplikaci spustit s parametrem -nosettings.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Chyba: Zadaný adresář pro data „%1“ neexistuje.</translation>
</message>
@@ -341,41 +355,41 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n sekunda</numerusform>
+ <numerusform>%n sekundy</numerusform>
+ <numerusform>%n sekund</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n minuta</numerusform>
+ <numerusform>%n minuty</numerusform>
+ <numerusform>%n minut</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n hodina</numerusform>
+ <numerusform>%n hodiny</numerusform>
+ <numerusform>%n hodin</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n den</numerusform>
+ <numerusform>%n dny</numerusform>
+ <numerusform>%n dní</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n týden</numerusform>
+ <numerusform>%n týdny</numerusform>
+ <numerusform>%n týdnů</numerusform>
</translation>
</message>
<message>
@@ -385,15 +399,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n rok</numerusform>
+ <numerusform>%n roky</numerusform>
+ <numerusform>%n let</numerusform>
</translation>
</message>
</context>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Soubor s nastavením není možné pÅ™eÄíst</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Do souboru s nastavením není možné zapisovat</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">Vývojáři %s</translation>
</message>
@@ -426,6 +448,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nastala chyba pÅ™i Ätení souboru %s! VÅ¡echny klíÄe se pÅ™eÄetly správnÄ›, ale data o transakcích nebo záznamy v adresáři mohou chybÄ›t Äi být nesprávné.</translation>
</message>
<message>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Chyba pÅ™i Ätení %s! Data o transakci mohou chybÄ›t a nebo být chybná.
+Ověřuji peněženku.</translation>
+ </message>
+ <message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
<translation type="unfinished">Chyba: záznam formátu souboru výpisu je nesprávný. Získáno "%s", oÄekáváno "format".</translation>
</message>
@@ -442,10 +469,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Chyba: Starší peněženky podporují pouze typy adres "legacy", "p2sh-segwit" a "bech32".</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Chyba: Nelze naslouchat příchozí spojení (listen vrátil chybu %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Odhad poplatku se nepodaÅ™il. Fallbackfee je zakázaný. PoÄkejte nÄ›kolik bloků nebo povolte -fallbackfee.</translation>
</message>
@@ -458,6 +481,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Neplatná Äástka pro -maxtxfee=&lt;amount&gt;: '%s' (musí být alespoň jako poplatek minrelay %s, aby transakce nezůstávaly trÄet)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Neplatný nebo poškozený soubor peers.dat (%s). Pokud věříš, že se jedná o chybu, prosím nahlas ji na %s. Jako řešení lze přesunout soubor (%s) z cesty (přejmenovat, přesunout nebo odstranit), aby se při dalším spuštění vytvořil nový.</translation>
+ </message>
+ <message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
<translation type="unfinished">Byla zadána více než jedna onion adresa. Použiju %s pro automaticky vytvořenou službu sítě Tor.</translation>
</message>
@@ -486,6 +513,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ProÅ™ezávání je nastaveno pod minimum %d MiB. Použij, prosím, nÄ›jaké vyšší Äíslo.</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">Režim proÄiÅ¡tÄ›ní je nekompatibilní s parametrem -reindex-chainstate. Místo toho použij plný -reindex.</translation>
+ </message>
+ <message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished">Prořezávání: poslední synchronizace peněženky proběhla před už prořezanými daty. Je třeba provést -reindex (tedy v případě prořezávacího režimu stáhnout znovu celý blockchain)</translation>
</message>
@@ -498,6 +529,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Databáze bloků obsahuje blok, který vypadá jako z budoucnosti, což může být kvůli Å¡patnÄ› nastavenému datu a Äasu na tvém poÄítaÄi. Nech databázi bloků pÅ™estavÄ›t pouze v případÄ›, že si jsi jistý, že máš na poÄítaÄi správný datum a Äas</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">Databáze indexu bloků obsahuje starší 'txindex'. Pro vyÄiÅ¡tÄ›ní obsazeného místa na disku, spusÅ¥te úplný -reindex, v opaÄném případÄ› tuto chybu ignorujte. Tato chybová zpráva nebude znovu zobrazena.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">Částka v transakci po odeÄtení poplatku je příliÅ¡ malá na odeslání</translation>
</message>
@@ -534,6 +569,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Byl poskytnut neznámý formát souboru peněženky "%s". Poskytněte prosím "bdb" nebo "sqlite".</translation>
</message>
<message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Nalezen nepodporovaný formát databáze řetězců. Restartujte prosím aplikaci s parametrem -reindex-chainstate. Tím dojde k opětovného sestavení databáze řetězců.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Peněženka úspěšnÄ› vytvoÅ™ena. Starší typ peněženek je oznaÄen za zastaralý a podpora pro vytváření a otevÅ™ení starých peněženek bude v budoucnu odebrána.</translation>
+ </message>
+ <message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
<translation type="unfinished">Varování: formát výpisu peněženky "%s" se neshoduje s formátem "%s", který byl urÄen příkazem.</translation>
</message>
@@ -570,6 +613,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nemohu přeložit -%s adresu: '%s'</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">Nelze nastavit -forcednsseed na hodnotu true, když je nastaveno -dnsseed na hodnotu false.</translation>
+ </message>
+ <message>
<source>Cannot set -peerblockfilters without -blockfilterindex.</source>
<translation type="unfinished">Nelze nastavit -peerblockfilters bez -blockfilterindex.</translation>
</message>
@@ -578,6 +625,98 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Není možné zapisovat do adresáře ' %s'; zkontrolujte oprávnění.</translation>
</message>
<message>
+ <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">Aktualizaci -txindex zahájenou pÅ™edchozí verzí není možné dokonÄit. Restartujte s pÅ™edchozí verzí a nebo spusÅ¥te úplný -reindex.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s požadavek pro naslouchání na portu %u. Tento port je považován za "špatný" a z tohoto důvodu je nepravděpodobné, že by se k němu připojovali některé uzly Bitcoin Core. Podrobnosti a úplný seznam špatných portů nalezneš v dokumentu doc/p2p-bad-ports.md.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Parametr -reindex-chainstate není kompatibilní s parametrem -blockfilterindex. PÅ™i použití -reindex-chainstate doÄasnÄ› zakažte parametr -blockfilterindex nebo nahraÄte parametr -reindex-chainstate parametrem -reindex pro úplné opÄ›tovné sestavení vÅ¡ech indexů.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Parametr -reindex-chainstate není kompatibilní s parametrem -coinstatsindex. PÅ™i použití -reindex-chainstate doÄasnÄ› zakažte parametr -coinstatsindex nebo nahraÄte parametr -reindex-chainstate parametrem -reindex pro úplné opÄ›tovné sestavení vÅ¡ech indexů.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Parametr -reindex-chainstate není kompatibilní s parametrem -txindex. PÅ™i použití -reindex-chainstate doÄasnÄ› zakažte parametr -txindex nebo nahraÄte parametr -reindex-chainstate parametrem -reindex pro úplné opÄ›tovné sestavení vÅ¡ech indexů.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">PÅ™edpokládaná platnost: poslední synchronizace peněženky pÅ™esahuje dostupná data bloků. Je potÅ™eba poÄkat až ověření Å™etÄ›zců v pozadí stáhne další bloky.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Nelze poskytovat konkrétní spojení a zároveň mít vyhledávání addrman odchozích spojení ve stejný Äas.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Chyba pÅ™i naÄtení %s: Externí podepisovací peněženka se naÄítá bez zkompilované podpory externího podpisovatele.</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Chyba: Data adres v peněžence není možné identifikovat jako data patřící k migrovaným peněženkám.</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">Chyba: Duplicitní popisovaÄe vytvoÅ™ené bÄ›hem migrace. VaÅ¡e peněženka může být poÅ¡kozena.</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Chyba: Transakce %s v peněžence nemůže být identifikována jako transakce patřící k migrovaným peněženkám.</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">Chyba: Nelze vytvoÅ™it popisovaÄe pro tuto starší peněženku. Nejprve se ujistÄ›te, že je peněženka odemÄená.</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Nelze přejmenovat neplatný peers.dat soubor. Prosím přesuňte jej, nebo odstraňte a zkuste znovu.</translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">Nekompatibilní možnost: -dnsseed=1 byla explicitně zadána, ale -onlynet zakazuje připojení k IPv4/IPv6</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">Odchozí spojení omezená do sítě Tor (-onlynet=onion), ale proxy pro dosažení sítě Tor je výslovně zakázána: -onion=0</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Odchozí spojení omezená do sítě Tor (-onlynet=onion), ale není zadán žádný proxy server pro přístup do sítě Tor: není zadán žádný z parametrů: -proxy, -onion, nebo -listenonion</translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">Nalezen nerozpoznatelný popisovaÄ. NaÄítaní peněženky %s
+
+Peněženka mohla být vytvořena v novější verzi.
+Zkuste prosím spustit nejnovější verzi softwaru.
+</translation>
+ </message>
+ <message>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished">Nepodporovaná úroveň pro logování úrovnÄ› -loglevel=%s. OÄekávaný parametr -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Platné kategorie: %s. Platné úrovnÄ› logování: %s.</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+NepodaÅ™ilo se vyÄistit nepovedenou migraci</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Nelze obnovit zálohu peněženky.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Nastavení pro %s je nastaveno pouze na síťi %s pokud jste v sekci [%s]</translation>
</message>
@@ -658,8 +797,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Chyba pÅ™i Ätení následujícího záznamu z databáze peněženky</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Chyba při aktualizaci stavové databáze blockchainu</translation>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">Chyba: Nelze pÅ™idat pouze-sledovací tx do peněženky pro Ätení</translation>
+ </message>
+ <message>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">Chyba: Nelze odstranit transakce které jsou pouze pro Ätení</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
@@ -674,6 +817,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Chyba: kontrolní souÄet souboru výpisu se neshoduje. VypoÄteno %s, oÄekáváno %s</translation>
</message>
<message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">Chyba: Nelze vytvoÅ™it novou peněženku pouze pro Ätení</translation>
+ </message>
+ <message>
<source>Error: Got key that was not hex: %s</source>
<translation type="unfinished">Chyba: obdržený klÃ­Ä nebyl hexadecimální: %s</translation>
</message>
@@ -694,10 +841,38 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Chyba: Žádné %s adresy nejsou dostupné.</translation>
</message>
<message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">Chyba: Ne všechny pouze-sledovací tx bylo možné smazat</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Chyba: Tato peněženka již používá SQLite</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">Chyba: Tato peněženka je již popisovaÄná peněženka</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">Chyba: Nelze zahájit Ätení vÅ¡ech záznamů v databázi</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Chyba: Nelze vytvořit zálohu tvojí peněženky</translation>
+ </message>
+ <message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">Chyba: nelze zpracovat verzi %u jako uint32_t</translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Chyba: Nelze pÅ™eÄíst vÅ¡echny záznamy v databázi</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">Chyba: Nelze odstranit data z adresáře pouze pro sledování</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
<translation type="unfinished">Chyba: nelze zapsat záznam do nové peněženky</translation>
</message>
@@ -734,6 +909,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Selhala úvodní zevrubná provÄ›rka. %s se ukonÄuje.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Vstup nenalezen a nebo je již utracen</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">Nedostatek prostředků</translation>
</message>
@@ -774,6 +953,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ve -whitelist byla zadána neplatná podsíť: '%s'</translation>
</message>
<message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">Chyba: Nelze naslouchat příchozí spojení (naslouchaÄ vrátil chybu %s)</translation>
+ </message>
+ <message>
<source>Loading P2P addresses…</source>
<translation type="unfinished">NaÄítám P2P adresy…</translation>
</message>
@@ -790,12 +973,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">NaÄítám peněženku...</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">ChybÄ›jící Äástka</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">Chybí data pro vyřešení odhadnutí velikosti transakce</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">V rámci -whitebind je třeba specifikovat i port: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Není specifikován proxy server. Použijte -proxy=&lt;ip&gt; nebo -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Není k dispozici žádná adresa</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -806,10 +997,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Prořezávání nemůže být zkonfigurováno s negativní hodnotou.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Prořezávací režim je nekompatibilní s -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Prořezávací režim není kompatibilní s -txindex.</translation>
</message>
@@ -910,6 +1097,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Částky v transakci nemohou být záporné</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Výstupní index změny transakce mimo rozsah</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">Transakce má v transakÄním zásobníku příliÅ¡ dlouhý Å™etÄ›zec</translation>
</message>
@@ -918,10 +1109,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transakce musí mít alespoň jednoho příjemce</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Transakce potřebuje změnu adresy, ale ta se nepodařila vygenerovat.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Transakce je příliš velká</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Není možné alokovat paměť pro -maxsigcachesize '%s' MiB</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished">Nedaří se mi pÅ™ipojit na %s na tomhle poÄítaÄi (operace bind vrátila chybu %s)</translation>
</message>
@@ -934,6 +1133,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nebylo možné vytvořit soubor PID '%s': %s</translation>
</message>
<message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">Nelze najít UTXO pro externí vstup</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation type="unfinished">NepodaÅ™ilo se mi vygenerovat poÄáteÄní klíÄe</translation>
</message>
@@ -946,10 +1149,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nelze otevřít %s pro zápis</translation>
</message>
<message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">Nelze rozebrat -maxuploadtarget: '%s'</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">Nemohu spustit HTTP server. Detaily viz v debug.log.</translation>
</message>
<message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">PÅ™ed migrací není možné peněženku odnaÄíst</translation>
+ </message>
+ <message>
<source>Unknown -blockfilterindex value %s.</source>
<translation type="unfinished">Neznámá -blockfilterindex hodnota %s.</translation>
</message>
@@ -970,12 +1181,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Neznámá nová pravidla aktivována (verzový bit %i)</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">Nepodporovaná logovací kategorie %s=%s.</translation>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">Nepodporovaný globální logovací úroveň -loglevel=%s. Možné hodnoty: %s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Aktualizuji databázi neutracených výstupů (UTXO)</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Nepodporovaná logovací kategorie %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -1045,6 +1256,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Vytvoř novou peněženku</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Minimalizovat</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Peněženka:</translation>
</message>
@@ -1192,9 +1407,9 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>Zpracován %n blok transakÄní historie.</numerusform>
+ <numerusform>Zpracovány %n bloky transakÄní historie.</numerusform>
+ <numerusform>Zpracováno %n bloků transakÄní historie</numerusform>
</translation>
</message>
<message>
@@ -1234,6 +1449,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">NaÄíst ÄásteÄnÄ› podepsanou Bitcoinovou transakci</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">NaÄíst PSBT ze &amp;schránky</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">NaÄíst ÄásteÄnÄ› podepsanou Bitcoinovou transakci ze schránky</translation>
</message>
@@ -1270,6 +1489,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Zavřít peněženku</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Obnovit peněženku...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Obnovit peněženku ze záložního souboru</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Zavřít všechny peněženky</translation>
</message>
@@ -1294,6 +1523,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nejsou dostupné žádné peněženky</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Data peněženky</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Nahrát zálohu peněženky</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Obnovit peněženku</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Název peněženky</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">O&amp;kno</translation>
</message>
@@ -1309,13 +1558,21 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 klient</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">Skryj</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">Zobraz</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n aktivní spojení s Bitcoinovou sítí.</numerusform>
+ <numerusform>%n aktivní spojení s Bitcoinovou sítí.</numerusform>
+ <numerusform>%n aktivních spojení s Bitcoinovou sítí.</numerusform>
</translation>
</message>
<message>
@@ -1339,6 +1596,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Zapnout síťovou aktivitu</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">PÅ™edběžná synchronizace hlaviÄky bloků (%1 %)...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Chyba: %1</translation>
</message>
@@ -1509,6 +1770,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Zkopírovat &amp;Äástku</translation>
</message>
<message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Zkopíruj &amp;ID transakce a výstupní index</translation>
+ </message>
+ <message>
<source>L&amp;ock unspent</source>
<translation type="unfinished">&amp;zamknout neutracené</translation>
</message>
@@ -1597,6 +1862,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">Nelze vypsat podepisovatele</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Nalezeno mnoho externích podpisovatelů</translation>
+ </message>
+</context>
+<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">NaÄíst peněženky</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">NaÄítám peněženky...</translation>
+ </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1624,6 +1906,34 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Obnovit peněženku</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Obnovuji peněženku &lt;b&gt;%1&lt;/b&gt; ...</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Obnovení peněženky selhalo</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Varování při obnovení peněženky</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Obnovení peněženky</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1798,9 +2108,29 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(z požadovaných %1 GB )</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n GB místa k dispozici</numerusform>
+ <numerusform>%n GB místa k dispozici</numerusform>
+ <numerusform>%n GB místa k dispozici</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(z %n GB požadovaných)</numerusform>
+ <numerusform>(z %n GB požadovaných)</numerusform>
+ <numerusform>(z %n GB požadovaných)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n GB požadovaných pro plný řetězec)</numerusform>
+ <numerusform>(%n GB požadovaných pro plný řetězec)</numerusform>
+ <numerusform>(%n GB požadovaných pro plný řetězec)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1814,9 +2144,9 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>(DostaÄující k obnovení zálohy %n dne staré)</numerusform>
+ <numerusform>(DostaÄující k obnovení záloh %n dnů staré)</numerusform>
+ <numerusform>(DostaÄující k obnovení záloh %n dnů staré)</numerusform>
</translation>
</message>
<message>
@@ -1848,10 +2178,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tohle je poprvé, co spouštíš %1, takže si můžeš zvolit, kam bude ukládat svá data.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Jakmile stiskneÅ¡ OK, %1 zaÄne stahovat a zpracovávat celý %4ový blockchain (%2 GB), poÄínaje nejstaršími transakcemi z roku %3, kdy byl %4 spuÅ¡tÄ›n.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Omezit uložiště blokového řetězce na</translation>
</message>
@@ -1868,6 +2194,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Prvotní synchronizace je velice nároÄná, a mohou se tak díky ní zaÄít na tvém poÄítaÄi projevovat dosud skryté hardwarové problémy. Pokaždé, když spustíš %1, bude stahování pokraÄovat tam, kde skonÄilo.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">Jakmile stiskneÅ¡ OK, %1 zaÄne stahovat a zpracovávat celý %4ový blockchain (%2 GB), poÄínaje nejstaršími transakcemi z roku %3, kdy byl %4 spuÅ¡tÄ›n.</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished">Pokud jsi omezil úložný prostor pro blockchain (tj. povolil jeho prořezávání), tak se historická data sice stáhnou a zpracují, ale následně zase smažou, aby nezabírala na disku místo.</translation>
</message>
@@ -1964,6 +2294,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Neznámé. Synchronizace hlaviÄek bloků (%1, %2%)...</translation>
</message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Neznámé. PÅ™edběžná synchronizace hlaviÄky bloků (%1, %2%)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -2020,6 +2354,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ZavÅ™ením se aplikace minimalizuje. Pokud je tato volba zaÅ¡krtnuta, tak se aplikace ukonÄí pouze zvolením Konec v menu.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Nastavení v tomto dialogu jsou přepsány příkazovým řádkem:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">OtevÅ™e konfiguraÄní soubor %1 z pracovního adresáře.</translation>
</message>
@@ -2048,14 +2386,44 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Obnovení tohoto nastavení vyžaduje opětovné stažení celého blockchainu.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">Maximální velikost vyrovnávací paměti databáze. Větší vyrovnávací paměť může přispět k rychlejší synchronizaci, avšak přínos pro většinu případů použití je méně výrazný. Snížení velikosti vyrovnávací paměti sníží využití paměti. Nevyužívaná paměť mempoolu je pro tuto vyrovnávací paměť sdílená.</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Nastaví poÄet vláken pro ověřování skriptů. Negativní hodnota odpovídá poÄtu jader procesoru, které chcete ponechat volné pro systém. </translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = automaticky, &lt;0 = nechat daný poÄet jader volný, výchozí: 0)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Toto povolí tobě nebo nástrojům třetích stran komunikovat pomocí uzlu skrz příkazový řádek a JSON-RPC příkazy.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">Povolit R&amp;PC server</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">P&amp;eněženka</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Zda nastavit odeÄtení poplatku od Äástky jako výchozí Äi nikoliv.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">OdeÄíst &amp;poplatek od výchozí Äástky</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">PokroÄilá nastavení</translation>
</message>
@@ -2072,6 +2440,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Utrácet i ještě nepotvrzené drobné</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Povolit &amp;PSBT kontrolu</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Zobrazit ovládací prvky PSBT.</translation>
+ </message>
+ <message>
<source>External Signer (e.g. hardware wallet)</source>
<translation type="unfinished">Externí podepisovatel (například hardwarová peněženka)</translation>
</message>
@@ -2176,6 +2554,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Zvol výchozí podjednotku, která se bude zobrazovat v programu a při posílání mincí.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">URL třetích stran (např. block exploreru), která se zobrazí v kontextovém menu v záložce Transakce. %s v URL se nahradí hashem transakce. Více URL odděl svislítkem |.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;URL třetích stran pro transakce</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Zda ukazovat možnosti pro ruÄní správu mincí nebo ne.</translation>
</message>
@@ -2200,10 +2586,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">nejbližší shoda "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Nastavení v tomto dialogu jsou pÅ™epsány konzolí nebo konfiguraÄním souborem:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;Budiž</translation>
</message>
@@ -2226,14 +2608,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Potvrzení obnovení nastavení</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">K aktivaci změn je potřeba restartovat klienta.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Aktuální nastavení bude uloženo v "%1".</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Klient se vypne, chceÅ¡ pokraÄovat?</translation>
</message>
<message>
@@ -2247,6 +2637,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">KonfiguraÄní soubor slouží k nastavování uživatelsky pokroÄilých možností, které mají pÅ™ednost pÅ™ed konfigurací z GUI. Parametry z příkazové řádky vÅ¡ak mají pÅ™ed konfiguraÄním souborem pÅ™ednost.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">PokraÄovat</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">Zrušit</translation>
</message>
@@ -2268,6 +2662,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Nelze pÅ™eÄíst nastavení "%1", %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2377,6 +2778,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nepodařilo se podepsat transakci: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Nelze podepsat vstup, když je peněženka uzamÄena.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">Nelze podepsat další vstupy.</translation>
</message>
@@ -2450,6 +2855,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transakce stále potřebuje podpis(y).</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Ale žádná peněženka není naÄtená.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Ale tato peněženka nemůže podepisovat transakce.)</translation>
</message>
@@ -2519,6 +2928,11 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
<translation type="unfinished">Protějšek</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Trvání</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Směr</translation>
@@ -2702,6 +3116,10 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
<translation type="unfinished">Aktuálně bloků</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Poslední transakce</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">Mapovaný nezávislý - Autonomní Systém používaný pro rozšírení vzájemného výběru protějsků.</translation>
</message>
@@ -2710,6 +3128,36 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
<translation type="unfinished">Mapovaný AS</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Zda předáváme adresy tomuto uzlu.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Přenášení adres</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Celkový poÄet adres obdržených od tohoto uzlu, které byly zpracovány (nezahrnuje adresy, které byly zahozeny díky omezení ovládání toku provozu)</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Celkový poÄet adres obdržených od tohoto uzlu, který byly zahozeny (nebyly zpracovány) díky omezení ovládání toku provozu.</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Zpracováno adres</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Adresy s omezením poÄtu pÅ™ijatých adres</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Typ klienta</translation>
</message>
@@ -2918,6 +3366,11 @@ Pokud vidíte tuto chybu, měli byste požádat, aby obchodník poskytl adresu k
<translation type="unfinished">1 &amp;rok</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">&amp;Zkopíruj IP/Masku</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">&amp;Odblokuj</translation>
</message>
@@ -3425,6 +3878,16 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">Zkontrolujte prosím svůj návrh transakce. Výsledkem bude ÄásteÄnÄ› podepsaná bitcoinová transakce (PSBT), kterou můžete uložit nebo kopírovat a poté podepsat napÅ™. pomocí offline %1 peněženky nebo hardwarové peněženky kompatibilní s PSBT.</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Přejete si vytvořit tuto transakci?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Prosím ověř svojí transakci. MůžeÅ¡ vytvoÅ™it a odeslat tuto transakci nebo vytvoÅ™it ČásteÄnÄ› Podepsanou Bitcoinovou Transakci (PSBT), kterou můžeÅ¡ uložit nebo zkopírovat a poté podepsat napÅ™. v offline %1 peněžence, nebo hardwarové peněžence kompatibilní s PSBT.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Prosím, zkontrolujte vaši transakci.</translation>
@@ -3477,16 +3940,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Poplatek vyšší než %1 je považován za absurdně vysoký.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Platební požadavek vypršel.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>Potvrzování by podle odhadu mÄ›lo zaÄít bÄ›hem %n bloku.</numerusform>
+ <numerusform>Potvrzování by podle odhadu mÄ›lo zaÄít bÄ›hem %n bloků.</numerusform>
+ <numerusform>Potvrzování by podle odhadu mÄ›lo zaÄít bÄ›hem %n bloků.</numerusform>
</translation>
</message>
<message>
@@ -3561,14 +4020,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">Zpráva:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Tohle je neověřený platební požadavek.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Tohle je ověřený platební požadavek.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Zadej oznaÄení této adresy; obojí se ti pak uloží do adresáře</translation>
</message>
@@ -3576,14 +4027,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Zpráva, která byla připojena k bitcoin: URI a která se ti pro přehled uloží k transakci. Poznámka: Tahle zpráva se neposílá s platbou po bitcoinové síti.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Komu:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Poznámka:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3745,35 +4188,41 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>(press q to shutdown and continue later)</source>
<translation type="unfinished">(stiskni q pro ukonÄení a pokraÄování pozdÄ›ji)</translation>
</message>
- </context>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">stiskněte q pro vypnutí</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">koliduje s transakcí o %1 konfirmacích</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/nepotvrzeno, %1</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/nepotvrzené, je v transakÄním zásobníku</translation>
</message>
<message>
- <source>in memory pool</source>
- <translation type="unfinished">v transakÄním zásobníku</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">není ani v transakÄním zásobníku</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/nepotvrzené, není v transakÄním zásobníku</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">zanechaná</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/nepotvrzeno</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 potvrzení</translation>
</message>
<message>
@@ -3823,9 +4272,9 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>dozraje za %n další blok</numerusform>
+ <numerusform>dozraje za %n další bloky</numerusform>
+ <numerusform>dozraje za %n dalších bloků</numerusform>
</translation>
</message>
<message>
@@ -4110,6 +4559,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">&amp;Upravit oznaÄení adresy</translation>
</message>
<message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Zobraz v %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Exportuj transakÄní historii</translation>
</message>
diff --git a/src/qt/locale/bitcoin_cy.ts b/src/qt/locale/bitcoin_cy.ts
index 6d8ee73324..ccff0580fd 100644
--- a/src/qt/locale/bitcoin_cy.ts
+++ b/src/qt/locale/bitcoin_cy.ts
@@ -660,6 +660,36 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts
index 53a7eae7d2..c78b6f194a 100644
--- a/src/qt/locale/bitcoin_da.ts
+++ b/src/qt/locale/bitcoin_da.ts
@@ -245,6 +245,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Indstillings filen 1%1 kan være korrupt eller invalid.</translation>
+ </message>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">Runaway undtagelse</translation>
+ </message>
+ <message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
<translation type="unfinished">Der skete en fatal fejl. %1 kan ikke længere fortsætte sikkert og vil afslutte.</translation>
</message>
@@ -252,10 +260,24 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Internal error</source>
<translation type="unfinished">Intern fejl</translation>
</message>
- </context>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">Der skete en intern fejl. %1 vil prøve at forsætte på sikker vis. Dette er en uventet fejl som kan reporteres som beskrevet under. </translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Vil du nulstille indstillinger til standardværdier eller afbryde uden at foretage ændringer?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Der opstod en fatal fejl. Tjek at indstillingsfilen er skrivbar, eller prøv at anvend -nosettings.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Fejl: Angivet datamappe “%1†eksisterer ikke.</translation>
</message>
@@ -268,6 +290,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Fejl: %1</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 har endnu ikke afsluttet på sikker vis…</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation type="unfinished">ukendt</translation>
</message>
@@ -280,6 +306,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Indtast en Bitcoin-adresse (fx %1)</translation>
</message>
<message>
+ <source>Unroutable</source>
+ <translation type="unfinished">Urutebar</translation>
+ </message>
+ <message>
<source>Internal</source>
<translation type="unfinished">Intern</translation>
</message>
@@ -294,11 +324,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Udgående</translation>
</message>
<message>
+ <source>Full Relay</source>
+ <extracomment>Peer connection type that relays all network information.</extracomment>
+ <translation type="unfinished">Fuld Videresend</translation>
+ </message>
+ <message>
+ <source>Block Relay</source>
+ <extracomment>Peer connection type that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">Blok Vidersend</translation>
+ </message>
+ <message>
<source>Manual</source>
<extracomment>Peer connection type established manually through one of several methods.</extracomment>
<translation type="unfinished">Brugervejledning</translation>
</message>
<message>
+ <source>Feeler</source>
+ <extracomment>Short-lived peer connection type that tests the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Føler</translation>
+ </message>
+ <message>
<source>Address Fetch</source>
<extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
<translation type="unfinished">Adresse Indhentning</translation>
@@ -361,6 +406,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Indstillingsfilen kunne ikke læses</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Indstillingsfilen kunne ikke skrives</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">Udviklerne af %s</translation>
</message>
@@ -373,10 +426,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">-maxtxfee er sat meget højt! Gebyrer så store risikeres betalt på en enkelt transaktion.</translation>
</message>
<message>
+ <source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
+ <translation type="unfinished">Kan ikke nedgradere tegnebogen fra version %i til version %i. Wallet-versionen uændret.</translation>
+ </message>
+ <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation type="unfinished">Kan ikke opnå en lås på datamappe %s. %s kører sansynligvis allerede.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Kan ikke opgradere en ikke-HD split wallet fra version %i til version %i uden at opgradere til at understøtte pre-split keypool. Brug venligst version %i eller ingen version angivet.</translation>
+ </message>
+ <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation type="unfinished">Distribueret under MIT-softwarelicensen; se den vedlagte fil %s eller %s</translation>
</message>
@@ -385,22 +446,58 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Fejl under læsning af %s! Alle nøgler blev læst korrekt, men transaktionsdata eller indgange i adressebogen kan mangle eller være ukorrekte.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Fejl: Lytning efter indkommende forbindelser mislykkedes (lytning resultarede i fejl %s)</translation>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Fejl ved læsning %s! Transaktionsdata kan mangle eller være forkerte. Genscanner tegnebogen.</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
+ <translation type="unfinished">Fejl: Dumpfilformat dokument er forkert. Fik "%s", forventet "format".</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile identifier record is incorrect. Got "%s", expected "%s".</source>
+ <translation type="unfinished">Fejl: Dumpfilformat dokument er forkert. Fik "%s", forventet "%s".</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
+ <translation type="unfinished">Fejl: Dumpfil-versionen understøttes ikke. Denne version af bitcoin-tegnebog understøtter kun version 1 dumpfiler. Fik dumpfil med version %s</translation>
+ </message>
+ <message>
+ <source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
+ <translation type="unfinished">Fejl: Ældre tegnebøger understøtter kun adressetyperne "legacy", "p2sh-segwit" og "bech32"</translation>
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Estimering af gebyr mislykkedes. Tilbagefaldsgebyr er deaktiveret. Vent et par blokke eller aktiver -fallbackfee.</translation>
</message>
<message>
+ <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">Fil %s eksisterer allerede. Hvis du er sikker på, at det er det, du vil have, så flyt det af vejen først.</translation>
+ </message>
+ <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation type="unfinished">Ugyldigt beløb for -maxtxfee=&lt;beløb&gt;: “%s†(skal være på mindst minrelay-gebyret på %s for at undgå hængende transaktioner)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Ugyldige eller korrupte peers.dat (%s). Hvis du mener, at dette er en fejl, bedes du rapportere det til %s. Som en løsning kan du flytte filen (%s) ud af vejen (omdøbe, flytte eller slette) for at få oprettet en ny ved næste start.</translation>
+ </message>
+ <message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
<translation type="unfinished">Mere end én onion-bindingsadresse er opgivet. Bruger %s til den automatiske oprettelse af Tor-onion-tjeneste.</translation>
</message>
<message>
+ <source>No dump file provided. To use createfromdump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">Der er ikke angivet nogen dumpfil. For at bruge createfromdump skal -dumpfile= &lt;filename&gt; angives.</translation>
+ </message>
+ <message>
+ <source>No dump file provided. To use dump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">Der er ikke angivet nogen dumpfil. For at bruge dump skal -dumpfile=&lt;filename&gt; angives.</translation>
+ </message>
+ <message>
+ <source>No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
+ <translation type="unfinished">Der er ikke angivet noget tegnebogsfilformat. For at bruge createfromdump skal -format=&lt;format&gt; angives.</translation>
+ </message>
+ <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation type="unfinished">Undersøg venligst at din computers dato og klokkeslet er korrekt indstillet! Hvis der er fejl i disse, vil %s ikke fungere korrekt.</translation>
</message>
@@ -425,6 +522,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Blokdatabasen indeholder en blok, som ser ud til at være fra fremtiden. Dette kan skyldes, at din computers dato og tid ikke er sat korrekt. Genopbyg kun blokdatabasen, hvis du er sikker på, at din computers dato og tid er korrekt</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">Blokindekset db indeholder et ældre 'txindex'. For at rydde den optagede diskplads skal du køre en fuld -reindex, ellers ignorere denne fejl. Denne fejlmeddelelse vil ikke blive vist igen.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">Transaktionsbeløbet er for lille til at sende, når gebyret er trukket fra</translation>
</message>
@@ -457,6 +558,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kan ikke genafspille blokke. Du er nødt til at genopbytte databasen ved hjælp af -reindex-chainstate.</translation>
</message>
<message>
+ <source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
+ <translation type="unfinished">Ukendt tegnebogsfilformat "%s" angivet. Angiv en af "bdb" eller "sqlite".</translation>
+ </message>
+ <message>
+ <source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
+ <translation type="unfinished">Advarsel: Dumpfile tegnebogsformatet "%s" matcher ikke kommandolinjens specificerede format "%s".</translation>
+ </message>
+ <message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
<translation type="unfinished">Advarsel: Private nøgler opdaget i tegnebog {%s} med deaktiverede private nøgler</translation>
</message>
@@ -465,6 +574,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Advarsel: Vi ser ikke ud til at være fuldt ud enige med andre knuder! Du kan være nødt til at opgradere, eller andre knuder kan være nødt til at opgradere.</translation>
</message>
<message>
+ <source>Witness data for blocks after height %d requires validation. Please restart with -reindex.</source>
+ <translation type="unfinished">Vidnedata for blokke efter højde %d kræver validering. Genstart venligst med -reindex.</translation>
+ </message>
+ <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation type="unfinished">Du er nødt til at genopbygge databasen ved hjælp af -reindex for at gå tilbage til ikke-beskåret tilstand. Dette vil downloade hele blokkæden igen</translation>
</message>
@@ -485,6 +598,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kan ikke finde -%s-adressen: “%sâ€</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">Kan ikke indstille -forcednsseed til true, når -dnsseed indstilles til false.</translation>
+ </message>
+ <message>
<source>Cannot set -peerblockfilters without -blockfilterindex.</source>
<translation type="unfinished">Kan ikke indstille -peerblockfilters uden -blockfilterindex.</translation>
</message>
@@ -493,6 +610,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kan ikke skrive til datamappe '%s'; tjek tilladelser.</translation>
</message>
<message>
+ <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">Opgraderingen af -txindex som er startet af en tidligere version kan ikke fuldføres. Genstart med den tidligere version eller kør en fuld -reindex.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Kan ikke levere specifikke forbindelser og få adrman til at finde udgående forbindelser på samme tid.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Fejlindlæsning %s: Ekstern underskriver-tegnebog indlæses uden ekstern underskriverunderstøttelse kompileret</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Kunne ikke omdøbe ugyldig peers.dat fil. Flyt eller slet den venligst og prøv igen.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Opsætningen af %s bliver kun udført på %s-netværk under [%s]-sektionen.</translation>
</message>
@@ -525,6 +658,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Indlæsning gennemført</translation>
</message>
<message>
+ <source>Dump file %s does not exist.</source>
+ <translation type="unfinished">Dumpfil %s findes ikke.</translation>
+ </message>
+ <message>
+ <source>Error creating %s</source>
+ <translation type="unfinished">Fejl skaber %s</translation>
+ </message>
+ <message>
<source>Error initializing block database</source>
<translation type="unfinished">Klargøring af blokdatabase mislykkedes</translation>
</message>
@@ -561,18 +702,50 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Fejl under læsning fra database; lukker ned.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Fejl under opgradering af kædetilstandsdatabase</translation>
+ <source>Error reading next record from wallet database</source>
+ <translation type="unfinished">Fejl ved læsning af næste post fra tegnebogsdatabase</translation>
+ </message>
+ <message>
+ <source>Error: Couldn't create cursor into database</source>
+ <translation type="unfinished">Fejl: Kunne ikke oprette markøren i databasen</translation>
</message>
<message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Fejl: Disk plads er lavt for %s</translation>
</message>
<message>
+ <source>Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
+ <translation type="unfinished">Fejl: Dumpfil kontrolsum stemmer ikke overens. Beregnet %s, forventet %s</translation>
+ </message>
+ <message>
+ <source>Error: Got key that was not hex: %s</source>
+ <translation type="unfinished">Fejl: Fik nøgle, der ikke var hex: %s</translation>
+ </message>
+ <message>
+ <source>Error: Got value that was not hex: %s</source>
+ <translation type="unfinished">Fejl: Fik værdi, der ikke var hex: %s</translation>
+ </message>
+ <message>
<source>Error: Keypool ran out, please call keypoolrefill first</source>
<translation type="unfinished">Fejl: Nøglepøl løb tør, tilkald venligst keypoolrefill først</translation>
</message>
<message>
+ <source>Error: Missing checksum</source>
+ <translation type="unfinished">Fejl: Manglende kontrolsum</translation>
+ </message>
+ <message>
+ <source>Error: No %s addresses available.</source>
+ <translation type="unfinished">Fejl: Ingen tilgængelige %s adresser.</translation>
+ </message>
+ <message>
+ <source>Error: Unable to parse version %u as a uint32_t</source>
+ <translation type="unfinished">Fejl: Kan ikke parse version %u som en uint32_t</translation>
+ </message>
+ <message>
+ <source>Error: Unable to write record to new wallet</source>
+ <translation type="unfinished">Fejl: Kan ikke skrive post til ny tegnebog</translation>
+ </message>
+ <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">Lytning på enhver port mislykkedes. Brug -listen=0, hvis du ønsker dette.</translation>
</message>
@@ -605,10 +778,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Sundhedstjek under initialisering mislykkedes. %s lukker ned.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Input ikke fundet eller allerede brugt</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">Manglende dækning</translation>
</message>
<message>
+ <source>Invalid -i2psam address or hostname: '%s'</source>
+ <translation type="unfinished">Ugyldig -i2psam-adresse eller værtsnavn: '%s'</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation type="unfinished">Ugyldig -onion-adresse eller værtsnavn: “%sâ€</translation>
</message>
@@ -657,12 +838,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Indlæser tegnebog...</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Manglende beløb</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">Manglende løsningsdata til estimering af transaktionsstørrelse</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Nødt til at angive en port med -whitebinde: “%sâ€</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Ingen proxyserver specificeret. Brug -proxy=&lt;ip&gt; eller -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Ingen adresser tilgængelige</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -685,6 +874,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Reducerer -maxconnections fra %d til %d på grund af systembegrænsninger.</translation>
</message>
<message>
+ <source>Replaying blocks…</source>
+ <translation type="unfinished">Genafspiller blokke...</translation>
+ </message>
+ <message>
<source>Rescanning…</source>
<translation type="unfinished">Genindlæser…</translation>
</message>
@@ -729,10 +922,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Angivet blokmappe “%s†eksisterer ikke.</translation>
</message>
<message>
+ <source>Starting network threads…</source>
+ <translation type="unfinished">Starter netværkstråde...</translation>
+ </message>
+ <message>
<source>The source code is available from %s.</source>
<translation type="unfinished">Kildekoden er tilgængelig fra %s.</translation>
</message>
<message>
+ <source>The specified config file %s does not exist</source>
+ <translation type="unfinished">Den angivne konfigurationsfil %s findes ikke</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to pay the fee</source>
<translation type="unfinished">Transaktionsbeløbet er for lille til at betale gebyret</translation>
</message>
@@ -761,6 +962,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transaktionsbeløb må ikke være negative</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Transaktions byttepenge outputindeks uden for intervallet</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">Transaktionen har en for lang hukommelsespuljekæde</translation>
</message>
@@ -769,6 +974,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transaktionen skal have mindst én modtager</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Transaktionen behøver en byttepenge adresse, men vi kan ikke generere den.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Transaktionen er for stor</translation>
</message>
@@ -793,6 +1002,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">U-istand til at generere nøgler</translation>
</message>
<message>
+ <source>Unable to open %s for writing</source>
+ <translation type="unfinished">Kan ikke åbne %s til skrivning</translation>
+ </message>
+ <message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">Kan ikke parse -maxuploadtarget: '%s'</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">Kunne ikke starte HTTP-server. Se fejlretningslog for detaljer.</translation>
</message>
@@ -813,18 +1030,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ukendt netværk anført i -onlynet: “%sâ€</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">Ikke understøttet logningskategori %s=%s.</translation>
+ <source>Unknown new rules activated (versionbit %i)</source>
+ <translation type="unfinished">Ukendte nye regler aktiveret (versionsbit %i)</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Opgraderer UTXO-database</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Ikke understøttet logningskategori %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Brugeragent-kommentar (%s) indeholder usikre tegn.</translation>
</message>
<message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">Verificerer blokke…</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)…</source>
<translation type="unfinished">Bekræfter tegnebog (/bøger)...</translation>
</message>
@@ -884,6 +1105,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Opret en ny tegnebog</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Minimér</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Tegnebog:</translation>
</message>
@@ -929,6 +1154,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Sikkerhedskopiér Tegnebog</translation>
</message>
<message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;Skift adgangskode</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">Signér &amp;besked</translation>
+ </message>
+ <message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
<translation type="unfinished">Signér beskeder med dine Bitcoin-adresser for at bevise, at de tilhører dig</translation>
</message>
@@ -941,6 +1174,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Verificér beskeder for at sikre, at de er signeret med de angivne Bitcoin-adresser</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">&amp;Indlæs PSBT fra fil...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">Ã…ben &amp;URI...</translation>
+ </message>
+ <message>
<source>Close Wallet…</source>
<translation type="unfinished">Luk Tegnebog...</translation>
</message>
@@ -969,10 +1210,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Faneværktøjslinje</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Synkroniserer hoveder (%1%)…</translation>
+ </message>
+ <message>
<source>Synchronizing with network…</source>
<translation type="unfinished">Synkroniserer med netværk …</translation>
</message>
<message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Indekserer blokke på disken…</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Bearbejder blokke på disken…</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Genindekserer blokke på disken…</translation>
+ </message>
+ <message>
<source>Connecting to peers…</source>
<translation type="unfinished">Forbinder til knuder...</translation>
</message>
@@ -1032,6 +1289,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Indlæs Partvist Signeret Bitcoin-Transaktion</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">Indlæs PSBT fra &amp;clipboard</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Indlæs Partvist Signeret Bitcoin-Transaktion fra udklipsholder</translation>
</message>
@@ -1068,6 +1329,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Luk tegnebog</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Gendan pung</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Gendan en pung, fra en backup fil. </translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Luk alle tegnebøgerne </translation>
</message>
@@ -1092,6 +1363,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ingen tegnebøger tilgængelige</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Tegnebogsdata</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Navn på tegnebog</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Vindue</translation>
</message>
@@ -1103,6 +1384,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1-klient</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Skjul</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">&amp;Vis</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1112,6 +1401,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Click for flere aktioner.</translation>
+ </message>
+ <message>
<source>Show Peers tab</source>
<extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
<translation type="unfinished">Vis værktøjslinjeknuder</translation>
@@ -1279,6 +1573,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kopiér beløb</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopiér adresse</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiér &amp;mærkat</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopiér &amp;beløb</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Kopiér transaktion &amp;ID og outputindeks</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">&amp;Fastlås ubrugte</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">&amp;LÃ¥s ubrugte op</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Kopiér mængde</translation>
</message>
@@ -1355,8 +1673,25 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Create wallet warning</source>
<translation type="unfinished">Advarsel for oprettelse af tegnebog</translation>
</message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Kan ikke liste underskrivere</translation>
+ </message>
</context>
<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">Indlæs Tegnebøger</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">Indlæser tegnebøger...</translation>
+ </message>
+</context>
+<context>
<name>OpenWalletActivity</name>
<message>
<source>Open wallet failed</source>
@@ -1375,7 +1710,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">Ã…ben Tegnebog</translation>
</message>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">Ã…bner Tegnebog &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
@@ -1450,6 +1790,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Beskriver-Pung</translation>
</message>
<message>
+ <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
+ <translation type="unfinished">Brug en ekstern signeringsenhed som en hardwaretegnebog. Konfigurer den eksterne underskriver skript i tegnebogspræferencerne først.</translation>
+ </message>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">Ekstern underskriver</translation>
+ </message>
+ <message>
<source>Create</source>
<translation type="unfinished">Opret</translation>
</message>
@@ -1457,7 +1805,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Compiled without sqlite support (required for descriptor wallets)</source>
<translation type="unfinished">Kompileret uden sqlite-understøttelse (krævet til beskriver-punge)</translation>
</message>
- </context>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Kompileret uden ekstern underskriver understøttelse (nødvendig for ekstern underskriver)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -1538,6 +1891,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Mindst %1 GB data vil blive gemt i denne mappe, og det vil vokse over tid.</translation>
@@ -1583,14 +1957,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Siden dette er første gang, programmet startes, kan du vælge, hvor %1 skal gemme sin data.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Når du klikker OK, vil %1 begynde at downloade og bearbejde den fulde %4-blokkæde (%2 GB), startende med de tidligste transaktioner i %3, da %4 først startede.</translation>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">Begræns blokkæde opbevaring til</translation>
</message>
<message>
<source>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>
<translation type="unfinished">Ændring af denne indstilling senere kræver gendownload af hele blokkæden. Det er hurtigere at downloade den komplette kæde først og beskære den senere. Slår nogle avancerede funktioner fra.</translation>
</message>
<message>
+ <source> GB</source>
+ <translation type="unfinished">GB</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">Denne indledningsvise synkronisering er meget krævende, og den kan potentielt afsløre hardwareproblemer med din computer, som du ellers ikke har lagt mærke til. Hver gang, du kører %1, vil den fortsætte med at downloade, hvor den sidst slap.</translation>
</message>
@@ -1621,6 +1999,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1 lukker ned…</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation type="unfinished">Luk ikke computeren ned, før dette vindue forsvinder.</translation>
</message>
@@ -1675,6 +2057,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
<translation type="unfinished">%1 synkroniserer lige nu. Hoveder og blokke bliver downloadet og valideret fra andre knuder. Processen fortsætter indtil den seneste blok nås.</translation>
</message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Ukendt. Synkroniserer Hoveder (%1, %2%)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1707,6 +2093,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Start %1 ved systemlogin</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Aktivering af beskæring reducerer betydeligt den diskplads, der kræves til at gemme transaktioner. Alle blokke er stadig fuldt validerede. Gendannelse af denne indstilling kræver gendownload af hele blokkæden.</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation type="unfinished">Størrelsen på &amp;databasens cache</translation>
</message>
@@ -1755,14 +2145,44 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ændring af denne indstilling senere kræver download af hele blokkæden igen.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">Maksimal størrelse på databasecache. En større cache kan bidrage til hurtigere synkronisering, hvorefter fordelen er mindre synlig i de fleste tilfælde. Sænkning af cachestørrelsen vil reducere hukommelsesforbruget. Ubrugt mempool-hukommelse deles for denne cache.</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Indstil antallet af scriptbekræftelsestråde. Negative værdier svarer til antallet af kerner, du ønsker at lade være frie til systemet.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = auto, &lt;0 = efterlad så mange kerner fri)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Dette giver dig eller et tredjepartsværktøj mulighed for at kommunikere med knuden gennem kommandolinje- og JSON-RPC-kommandoer.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">Aktiver &amp;RPC-server</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">&amp;Tegnebog</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Hvorvidt der skal trækkes gebyr fra beløb som standard eller ej.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Træk &amp;gebyr fra beløbet som standard</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">Ekspert</translation>
</message>
@@ -1779,6 +2199,28 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Brug ubekræftede byttepenge</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Aktiver &amp;PSBT styring</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Om PSBT styring skal vises.</translation>
+ </message>
+ <message>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">Ekstern underskriver (f.eks. hardwaretegnebog)</translation>
+ </message>
+ <message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">&amp;Ekstern underskrivers scriptsti</translation>
+ </message>
+ <message>
+ <source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
+ <translation type="unfinished">Fuld sti til et Bitcoin Core-kompatibelt script (f.eks. C:\Downloads\hwi.exe eller /Users/you/Downloads/hwi.py). Pas på: malware kan stjæle dine mønter!</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">Åbn automatisk Bitcoin-klientens port på routeren. Dette virker kun, når din router understøtter UPnP, og UPnP er aktiveret.</translation>
</message>
@@ -1787,6 +2229,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Konfigurér port vha. &amp;UPnP</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Åbn automatisk Bitcoin-klientporten på routeren. Dette virker kun, når din router understøtter NAT-PMP, og den er aktiveret. Den eksterne port kan være tilfældig.</translation>
+ </message>
+ <message>
+ <source>Map port using NA&amp;T-PMP</source>
+ <translation type="unfinished">Kortport ved hjælp af NA&amp;T-PMP</translation>
+ </message>
+ <message>
<source>Accept connections from outside.</source>
<translation type="unfinished">Acceptér forbindelser udefra.</translation>
</message>
@@ -1819,6 +2269,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Vindue</translation>
</message>
<message>
+ <source>Show the icon in the system tray.</source>
+ <translation type="unfinished">Vis ikonet i proceslinjen.</translation>
+ </message>
+ <message>
+ <source>&amp;Show tray icon</source>
+ <translation type="unfinished">&amp;Vis bakkeikon</translation>
+ </message>
+ <message>
<source>Show only a tray icon after minimizing the window.</source>
<translation type="unfinished">Vis kun et statusikon efter minimering af vinduet.</translation>
</message>
@@ -1851,6 +2309,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Vælg standard for underopdeling af enhed, som skal vises i brugergrænsefladen og ved afsendelse af bitcoins.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Tredjeparts-URL'er (f.eks. en blokudforsker), der vises på fanen Transaktioner som genvejsmenupunkter. %s i URL'en erstattes af transaktions-hash. Flere URL'er er adskilt af lodret streg |.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;Tredjeparts transaktions-URL'er</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Hvorvidt egenskaber for coin-styring skal vises eller ej.</translation>
</message>
@@ -1863,8 +2329,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Brug separate SOCKS&amp;5 proxy, for at nå fælle via Tor-onion-tjenester:</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Valgmuligheder sat i denne dialog er overskrevet af kommandolinjen eller i konfigurationsfilen:</translation>
+ <source>Monospaced font in the Overview tab:</source>
+ <translation type="unfinished">Monospaced skrifttype på fanen Oversigt:</translation>
+ </message>
+ <message>
+ <source>embedded "%1"</source>
+ <translation type="unfinished">indlejret "%1"</translation>
+ </message>
+ <message>
+ <source>closest matching "%1"</source>
+ <translation type="unfinished">tættest matchende "%1"</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -1875,6 +2349,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Annullér</translation>
</message>
<message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Kompileret uden ekstern underskriver understøttelse (nødvendig for ekstern underskriver)</translation>
+ </message>
+ <message>
<source>default</source>
<translation type="unfinished">standard</translation>
</message>
@@ -1884,14 +2363,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Bekræft nulstilling af indstillinger</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Genstart af klienten er nødvendig for at aktivere ændringer.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Klienten vil lukke ned. Vil du fortsætte?</translation>
</message>
<message>
@@ -1905,6 +2387,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Konfigurationsfilen bruges til at opsætte avancerede brugerindstillinger, som tilsidesætter indstillingerne i den grafiske brugerflade. Derudover vil eventuelle kommandolinjetilvalg tilsidesætte denne konfigurationsfil.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">Forsæt</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">Fortryd</translation>
</message>
@@ -2031,6 +2517,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kunne ikke signere transaktion: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Kan ikke signere inputs, mens tegnebogen er låst.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">Kunne ikke signere flere input.</translation>
</message>
@@ -2063,6 +2553,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Gem Transaktionsdata</translation>
</message>
<message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">Delvist underskrevet transaktion (Binær)</translation>
+ </message>
+ <message>
<source>PSBT saved to disk.</source>
<translation type="unfinished">PSBT gemt på disk.</translation>
</message>
@@ -2099,6 +2594,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transaktion mangler stadig signatur(er).</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Men ingen tegnebog er indlæst.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Men denne tegnebog kan ikke signere transaktioner.)</translation>
</message>
@@ -2134,6 +2633,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">'bitcoin://' er ikke et gyldigt URI. Brug 'bitcoin:' istedet.</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.
+Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
+If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation type="unfinished">Kan ikke behandle betalingsanmodning, fordi BIP70 ikke understøttes.
+På grund af udbredte sikkerhedsfejl i BIP70 anbefales det på det kraftigste, at enhver købmands instruktioner om at skifte tegnebog ignoreres.
+Hvis du modtager denne fejl, skal du anmode forhandleren om en BIP21-kompatibel URI.</translation>
+ </message>
+ <message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
<translation type="unfinished">URI kan ikke tolkes! Dette kan skyldes en ugyldig Bitcoin-adresse eller forkert udformede URL-parametre.</translation>
</message>
@@ -2325,6 +2832,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Synkroniserede blokke</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Sidste transaktion</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">Afbildning fra Autonome Systemer (et Internet-Protocol-rutefindingsprefiks) til IP-adresser som bruges til at diversificere knudeforbindelser. Den engelske betegnelse er "asmap".</translation>
</message>
@@ -2333,6 +2844,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Autonomt-System-afbildning</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Om vi videresender adresser til denne peer.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Adresserelæ</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Adresser Behandlet</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Adresser Hastighedsbegrænset</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Brugeragent</translation>
</message>
@@ -2361,18 +2892,55 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tilladelser</translation>
</message>
<message>
+ <source>The direction and type of peer connection: %1</source>
+ <translation type="unfinished">Retningen og typen af peer-forbindelse: %1</translation>
+ </message>
+ <message>
+ <source>Direction/Type</source>
+ <translation type="unfinished">Retning/Type</translation>
+ </message>
+ <message>
+ <source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
+ <translation type="unfinished">Netværksprotokollen, som denne peer er forbundet via: IPv4, IPv6, Onion, I2P eller CJDNS.</translation>
+ </message>
+ <message>
<source>Services</source>
<translation type="unfinished">Tjenester</translation>
</message>
<message>
+ <source>Whether the peer requested us to relay transactions.</source>
+ <translation type="unfinished">Om peeren anmodede os om at videresende transaktioner.</translation>
+ </message>
+ <message>
+ <source>Wants Tx Relay</source>
+ <translation type="unfinished">Vil have transaktion videresend</translation>
+ </message>
+ <message>
+ <source>High bandwidth BIP152 compact block relay: %1</source>
+ <translation type="unfinished">BIP152 kompakt blokrelæ med høj bredbånd: %1</translation>
+ </message>
+ <message>
+ <source>High Bandwidth</source>
+ <translation type="unfinished">Højt Bredbånd</translation>
+ </message>
+ <message>
<source>Connection Time</source>
<translation type="unfinished">Forbindelsestid</translation>
</message>
<message>
+ <source>Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
+ <translation type="unfinished">Forløbet tid siden en ny blok, der bestod indledende gyldighedstjek, blev modtaget fra denne peer.</translation>
+ </message>
+ <message>
<source>Last Block</source>
<translation type="unfinished">Sidste Blok</translation>
</message>
<message>
+ <source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
+ <extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
+ <translation type="unfinished">Forløbet tid siden en ny transaktion, der blev accepteret i vores mempool, blev modtaget fra denne peer.</translation>
+ </message>
+ <message>
<source>Last Send</source>
<translation type="unfinished">Seneste afsendelse</translation>
</message>
@@ -2437,6 +3005,53 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Udgående:</translation>
</message>
<message>
+ <source>Inbound: initiated by peer</source>
+ <extracomment>Explanatory text for an inbound peer connection.</extracomment>
+ <translation type="unfinished">Indgående: initieret af peer</translation>
+ </message>
+ <message>
+ <source>Outbound Full Relay: default</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</extracomment>
+ <translation type="unfinished">Udgående fuld relæ: standard</translation>
+ </message>
+ <message>
+ <source>Outbound Block Relay: does not relay transactions or addresses</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">Udgående blokrelæ: videresender ikke transaktioner eller adresser</translation>
+ </message>
+ <message>
+ <source>Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Udgående manual: tilføjet ved hjælp af RPC %1 eller %2/%3 konfigurationsmuligheder</translation>
+ </message>
+ <message>
+ <source>Outbound Feeler: short-lived, for testing addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Udgående fejl: kortvarig, til test af adresser</translation>
+ </message>
+ <message>
+ <source>Outbound Address Fetch: short-lived, for soliciting addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</extracomment>
+ <translation type="unfinished">Udgående adressehentning: kortvarig, til at anmode om adresser</translation>
+ </message>
+ <message>
+ <source>we selected the peer for high bandwidth relay</source>
+ <translation type="unfinished">vi valgte denne peer for høj bredbånd relæ</translation>
+ </message>
+ <message>
+ <source>the peer selected us for high bandwidth relay</source>
+ <translation type="unfinished">peeren valgte os til høj bredbånd relæ</translation>
+ </message>
+ <message>
+ <source>no high bandwidth relay selected</source>
+ <translation type="unfinished">ingen høj bredbånd relæ valgt</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;Kopiér adresse</translation>
+ </message>
+ <message>
<source>&amp;Disconnect</source>
<translation type="unfinished">&amp;Afbryd forbindelse</translation>
</message>
@@ -2445,6 +3060,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">1 &amp;time</translation>
</message>
<message>
+ <source>1 d&amp;ay</source>
+ <translation type="unfinished">1 &amp;dag</translation>
+ </message>
+ <message>
<source>1 &amp;week</source>
<translation type="unfinished">1 &amp;uge</translation>
</message>
@@ -2453,6 +3072,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">1 &amp;Ã¥r</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">&amp;Kopiér IP/Netmask</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">&amp;Fjern bandlysning</translation>
</message>
@@ -2469,6 +3093,28 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Eksekverer kommando ved brug af "%1" tegnebog</translation>
</message>
<message>
+ <source>Welcome to the %1 RPC console.
+Use up and down arrows to navigate history, and %2 to clear screen.
+Use %3 and %4 to increase or decrease the font size.
+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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Velkommen til %1 RPC-konsollen.
+Brug op- og nedpilene til at navigere i historikken og %2 til at rydde skærmen.
+Brug %3 og %4 til at øge eller formindske skriftstørrelsen.
+Skriv %5 for at få en oversigt over tilgængelige kommandoer.
+For mere information om brug af denne konsol, skriv %6.
+
+%7 ADVARSEL: Svindlere har været aktive og bedt brugerne om at skrive kommandoer her og stjæle deres tegnebogsindhold. Brug ikke denne konsol uden fuldt ud at forstå konsekvenserne af en kommando.%8</translation>
+ </message>
+ <message>
+ <source>Executing…</source>
+ <extracomment>A console message indicating an entered command is currently being executed.</extracomment>
+ <translation type="unfinished">Udfører...</translation>
+ </message>
+ <message>
<source>Yes</source>
<translation type="unfinished">Ja</translation>
</message>
@@ -2572,6 +3218,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kopiér &amp;URI</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopiér adresse</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiér &amp;mærkat</translation>
+ </message>
+ <message>
+ <source>Copy &amp;message</source>
+ <translation type="unfinished">Kopiér &amp;besked</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopiér &amp;beløb</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">Kunne ikke låse tegnebog op.</translation>
</message>
@@ -2615,6 +3277,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kopiér &amp;adresse</translation>
</message>
<message>
+ <source>&amp;Verify</source>
+ <translation type="unfinished">&amp;Bekræft</translation>
+ </message>
+ <message>
+ <source>Verify this address on e.g. a hardware wallet screen</source>
+ <translation type="unfinished">Bekræft denne adresse på f.eks. en hardwaretegnebogs skærm</translation>
+ </message>
+ <message>
<source>&amp;Save Image…</source>
<translation type="unfinished">&amp;Gem billede...</translation>
</message>
@@ -2765,6 +3435,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Skjul indstillinger for transaktionsgebyr</translation>
</message>
<message>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation type="unfinished">Angiv et brugerdefineret gebyr pr. kB (1.000 bytes) af transaktionens virtuelle størrelse.
+
+Bemærk: Da gebyret beregnes på per-byte-basis, ville en gebyrsats på "100 satoshis pr. kvB" for en transaktionsstørrelse på 500 virtuelle bytes (halvdelen af 1 kvB) i sidste ende kun give et gebyr på 50 satoshis.</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">På tidspunkter, hvor der er færre transaktioner, end der er plads til i nye blokke, kan minere og videresendende knuder gennemtvinge et minimumsgebyr. Du kan vælge kun at betale dette minimumsgebyr, men vær opmærksom på, at det kan resultere i en transaktion, der aldrig bliver bekræftet, hvis mængden af nye bitcoin-transaktioner stiger til mere, end hvad netværket kan behandle ad gangen.</translation>
</message>
@@ -2773,6 +3451,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Et for lavt gebyr kan resultere i en transaktion, der aldrig bekræftes (læs værktøjstippet)</translation>
</message>
<message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks…)</source>
+ <translation type="unfinished">(Smart gebyr er ikke initialiseret endnu. Dette tager normalt et par blokke...)</translation>
+ </message>
+ <message>
<source>Confirmation time target:</source>
<translation type="unfinished">Mål for bekræftelsestid:</translation>
</message>
@@ -2833,6 +3515,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1 (%2 blokke)</translation>
</message>
<message>
+ <source>Sign on device</source>
+ <extracomment>"device" usually means a hardware wallet.</extracomment>
+ <translation type="unfinished">Underskriv på enhed</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">Tilslut din hardwaretegnebog først.</translation>
+ </message>
+ <message>
+ <source>Set external signer script path in Options -&gt; Wallet</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Indstil ekstern underskriver scriptsti i Indstillinger -&gt; Tegnebog</translation>
+ </message>
+ <message>
<source>Cr&amp;eate Unsigned</source>
<translation type="unfinished">L&amp;av usigneret</translation>
</message>
@@ -2849,14 +3545,41 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1 til %2</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details…"</source>
+ <translation type="unfinished">For at vurdere modtager listen tryk "Vis Detaljer..."</translation>
+ </message>
+ <message>
+ <source>Sign failed</source>
+ <translation type="unfinished">Underskrivningen fejlede</translation>
+ </message>
+ <message>
+ <source>External signer not found</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Ekstern underskriver ikke fundet</translation>
+ </message>
+ <message>
+ <source>External signer failure</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Ekstern underskriver fejl</translation>
+ </message>
+ <message>
<source>Save Transaction Data</source>
<translation type="unfinished">Gem Transaktionsdata</translation>
</message>
<message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">Delvist underskrevet transaktion (Binær)</translation>
+ </message>
+ <message>
<source>PSBT saved</source>
<translation type="unfinished">PSBT gemt</translation>
</message>
<message>
+ <source>External balance:</source>
+ <translation type="unfinished">Ekstern balance:</translation>
+ </message>
+ <message>
<source>or</source>
<translation type="unfinished">eller</translation>
</message>
@@ -2870,6 +3593,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Gennemse venligst dit transaktionsforslag. Dette vil producere en Partvist Signeret Bitcoin Transaktion (PSBT), som du kan gemme eller kopiere, og så signere med f.eks. en offline %1 pung, eller en PSBT-kompatibel maskinelpung.</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Vil du oprette denne transaktion?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Gennemgå venligst din transaktion. Du kan oprette og sende denne transaktion eller oprette en delvist underskrevet Bitcoin-transaktion (PSBT), som du kan gemme eller kopiere og derefter underskrive med, f.eks. en offline %1 tegnebog eller en PSBT-kompatibel hardwaretegnebog.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Venligst, vurder din transaktion.</translation>
@@ -2922,10 +3655,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Et gebyr højere end %1 opfattes som et absurd højt gebyr.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Betalingsanmodning er udløbet.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3005,14 +3734,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Besked:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Dette er en uautentificeret betalingsanmodning.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Dette er en autentificeret betalingsanmodning.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Indtast et mærkat for denne adresse for at føje den til listen over brugte adresser</translation>
</message>
@@ -3020,11 +3741,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">En besked, som blev føjet til “bitcoin:â€-URI'en, som vil gemmes med transaktionen til din reference. Bemærk: Denne besked vil ikke blive sendt over Bitcoin-netværket.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Betal til:</translation>
- </message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -3185,35 +3902,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>(press q to shutdown and continue later)</source>
<translation type="unfinished">(tast q for at lukke ned og fortsætte senere)</translation>
</message>
- </context>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">tryk på q for at lukke</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">i konflikt med en transaktion, der har %1 bekræftelser</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/ubekræftet, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">i hukommelsespulje</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ikke i hukommelsespulje</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">opgivet</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/ubekræftet</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 bekræftelser</translation>
</message>
<message>
@@ -3509,6 +4222,51 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Interval...</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopiér adresse</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiér &amp;mærkat</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopiér &amp;beløb</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">Kopiér transaktion &amp;ID</translation>
+ </message>
+ <message>
+ <source>Copy &amp;raw transaction</source>
+ <translation type="unfinished">Kopiér &amp;rå transaktion</translation>
+ </message>
+ <message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">Kopiér alle transaktion &amp;oplysninger </translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">&amp;Vis transaktionsoplysninger</translation>
+ </message>
+ <message>
+ <source>Increase transaction &amp;fee</source>
+ <translation type="unfinished">Hæv transaktions &amp;gebyr</translation>
+ </message>
+ <message>
+ <source>A&amp;bandon transaction</source>
+ <translation type="unfinished">&amp;Opgiv transaction</translation>
+ </message>
+ <message>
+ <source>&amp;Edit address label</source>
+ <translation type="unfinished">&amp;Rediger adresseetiket</translation>
+ </message>
+ <message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Vis på %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Eksportér transaktionshistorik</translation>
</message>
@@ -3633,6 +4391,10 @@ Gå til Fil &gt; Åbn Pung for, at indlæse en pung.
<translation type="unfinished">Nyt gebyr:</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Advarsel: Dette kan betale det ekstra gebyr ved at reducere byttepengesoutputs eller tilføje inputs, når det er nødvendigt. Det kan tilføje et nyt byttepengesoutput, hvis et ikke allerede eksisterer. Disse ændringer kan potentielt lække privatlivets fred.</translation>
+ </message>
+ <message>
<source>Confirm fee bump</source>
<translation type="unfinished">Bekræft gebyrforøgelse</translation>
</message>
@@ -3653,6 +4415,10 @@ Gå til Fil &gt; Åbn Pung for, at indlæse en pung.
<translation type="unfinished">Kunne ikke gennemføre transaktionen</translation>
</message>
<message>
+ <source>Can't display address</source>
+ <translation type="unfinished">Adressen kan ikke vises</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">Standard tegnebog</translation>
</message>
diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts
index cdfb8d77dc..732318c5a8 100644
--- a/src/qt/locale/bitcoin_de.ts
+++ b/src/qt/locale/bitcoin_de.ts
@@ -246,6 +246,10 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Einstellungsdatei %1 ist eventuell korrumpiert oder ungültig.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Auslaufende Ausnahme</translation>
</message>
@@ -265,6 +269,16 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Möchten Sie die Einstellungen auf die Standardwerte zurücksetzen oder den Vorgang abbrechen, ohne Änderungen vorzunehmen?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Ein schwerwiegender Fehler ist aufgetreten. Prüfen Sie, ob die Einstellungsdatei beschreibbar ist, oder versuchen Sie, das Programm mit "-nosettings" auszuführen.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Fehler: Angegebenes Datenverzeichnis "%1" existiert nicht.</translation>
</message>
@@ -323,7 +337,7 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<message>
<source>Manual</source>
<extracomment>Peer connection type established manually through one of several methods.</extracomment>
- <translation type="unfinished">Anleitung</translation>
+ <translation type="unfinished">Manuell</translation>
</message>
<message>
<source>Feeler</source>
@@ -354,36 +368,36 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n Sekunde(n)</numerusform>
+ <numerusform>%n Sekunde(n)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n Minute(n)</numerusform>
+ <numerusform>%n Minute(n)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%nStunde(n)</numerusform>
+ <numerusform>%nStunde(n)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%nTag(e)</numerusform>
+ <numerusform>%nTag(e)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n Woche(n)</numerusform>
+ <numerusform>%n Woche(n)</numerusform>
</translation>
</message>
<message>
@@ -393,8 +407,8 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%nJahr(e)</numerusform>
+ <numerusform>%nJahr(e)</numerusform>
</translation>
</message>
</context>
@@ -441,6 +455,10 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<translation type="unfinished">Lesen von %s fehlgeschlagen! Alle Schlüssel wurden korrekt gelesen, Transaktionsdaten bzw. Adressbucheinträge fehlen aber möglicherweise oder sind inkorrekt.</translation>
</message>
<message>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Fehler beim Lesen von %s! Transaktionsdaten fehlen oder sind nicht korrekt. Wallet wird erneut gescannt.</translation>
+ </message>
+ <message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
<translation type="unfinished">Fehler: Dumpdatei Format Eintrag ist Ungültig. Habe "%s" bekommen, aber "format" erwartet.</translation>
</message>
@@ -457,10 +475,6 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<translation type="unfinished">Fehler: Althergebrachte Brieftaschen unterstützen nur die Adresstypen "legacy", "p2sh-segwit" und "bech32".</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Fehler: Abhören nach eingehenden Verbindungen fehlgeschlagen (listen meldete Fehler %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Die Gebührenabschätzung schlug fehl. Fallbackfee ist deaktiviert. Warten Sie ein paar Blöcke oder aktivieren Sie -fallbackfee.</translation>
</message>
@@ -473,6 +487,10 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<translation type="unfinished">Ungültiger Betrag für -maxtxfee=&lt;amount&gt;: '%s' (muss mindestens die minimale Weiterleitungsgebühr in Höhe von %s sein, um zu verhindern, dass Transaktionen nicht bearbeitet werden)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Ungültige oder beschädigte peers.dat (%s). Wenn Sie glauben, dass dies ein Fehler ist, melden Sie ihn bitte an %s. Zur Abhilfe können Sie die Datei (%s) aus dem Weg räumen (umbenennen, verschieben oder löschen), so dass beim nächsten Start eine neue Datei erstellt wird.</translation>
+ </message>
+ <message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
<translation type="unfinished">Mehr als eine Onion-Bindungsadresse angegeben. Verwende %s für den automatisch erstellten Tor-Onion-Dienst.</translation>
</message>
@@ -501,6 +519,10 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<translation type="unfinished">Kürzungsmodus wurde kleiner als das Minimum in Höhe von %d MiB konfiguriert. Bitte verwenden Sie einen größeren Wert.</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">Der Prune-Modus ist mit -reindex-chainstate nicht kompatibel. Verwende stattdessen den vollen -reindex.</translation>
+ </message>
+ <message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished">Prune (Kürzung): Die letzte Synchronisation der Wallet liegt vor gekürzten (gelöschten) Blöcken. Es ist ein -reindex (erneuter Download der gesamten Blockchain im Fall eines gekürzten Knotens) notwendig.</translation>
</message>
@@ -513,6 +535,10 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
<translation type="unfinished">Die Block-Datenbank enthält einen Block, der in der Zukunft auftaucht. Dies kann daran liegen, dass die Systemzeit Ihres Computers falsch eingestellt ist. Stellen Sie die Block-Datenbank nur wieder her, wenn Sie sich sicher sind, dass Ihre Systemzeit korrekt eingestellt ist.</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">Die Blockindexdatenbank enthält einen veralteten 'txindex'. Um den belegten Speicherplatz frei zu geben, führen Sie ein vollständiges -reindex aus, ansonsten ignorieren Sie diesen Fehler. Diese Fehlermeldung wird nicht noch einmal angezeigt.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">Der Transaktionsbetrag ist zu klein, um ihn nach Abzug der Gebühr zu senden.</translation>
</message>
@@ -550,6 +576,14 @@ Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
Bitte nutzen Sie entweder "bdb" oder "sqlite".</translation>
</message>
<message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Nicht unterstütztes Chainstate-Datenbankformat gefunden. Bitte starte mit -reindex-chainstate neu. Dadurch wird die Chainstate-Datenbank neu erstellt.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Wallet erfolgreich erstellt. Der Legacy-Wallet-Typ ist veraltet und die Unterstützung für das Erstellen und Öffnen von Legacy-Wallets wird in Zukunft entfernt.</translation>
+ </message>
+ <message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
<translation type="unfinished">Warnung: Dumpdatei Wallet Format "%s" passt nicht zum auf der Kommandozeile angegebenen Format "%s".</translation>
</message>
@@ -586,6 +620,10 @@ Bitte nutzen Sie entweder "bdb" oder "sqlite".</translation>
<translation type="unfinished">Kann Adresse in -%s nicht auflösen: '%s'</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">Kann -forcednsseed nicht auf true setzen, wenn -dnsseed auf false gesetzt ist.</translation>
+ </message>
+ <message>
<source>Cannot set -peerblockfilters without -blockfilterindex.</source>
<translation type="unfinished">Kann -peerblockfilters nicht ohne -blockfilterindex setzen.</translation>
</message>
@@ -594,6 +632,46 @@ Bitte nutzen Sie entweder "bdb" oder "sqlite".</translation>
<translation type="unfinished">Es konnte nicht in das Datenverzeichnis '%s' geschrieben werden; Überprüfen Sie die Berechtigungen.</translation>
</message>
<message>
+ <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">Das von einer früheren Version gestartete -txindex-Upgrade kann nicht abgeschlossen werden. Starten Sie mit der vorherigen Version neu oder führen Sie ein vollständiges -reindex aus.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s Aufforderung, auf Port %u zu lauschen. Dieser Port wird als "schlecht" eingeschätzt und es ist daher unwahrscheinlich, dass sich Bitcoin Core Peers mit ihm verbinden. Siehe doc/p2p-bad-ports.md für Details und eine vollständige Liste.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Die Option -reindex-chainstate ist nicht mit -blockfilterindex kompatibel. Bitte deaktiviere blockfilterindex vorübergehend, während du -reindex-chainstate verwendest oder ersetze -reindex-chainstate durch -reindex, um alle Indexe vollständig neu zu erstellen.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Die Option -reindex-chainstate ist nicht mit -coinstatsindex kompatibel. Bitte deaktiviere coinstatsindex vorübergehend, während du -reindex-chainstate verwendest oder ersetze -reindex-chainstate durch -reindex, um alle Indexe vollständig neu zu erstellen.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Die Option -reindex-chainstate ist nicht mit -txindex kompatibel. Bitte deaktiviere txindex vorübergehend, während du -reindex-chainstate verwendest oder ersetze -reindex-chainstate durch -reindex, um alle Indexe vollständig neu zu erstellen.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Angenommen gültig: Die letzte Wallet-Synchronisation geht über die verfügbaren Blockdaten hinaus. Sie müssen warten, bis die Hintergrundvalidierungskette weitere Blöcke herunterlädt.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Es ist nicht möglich, bestimmte Verbindungen anzubieten und gleichzeitig addrman ausgehende Verbindungen finden zu lassen.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Fehler beim Laden von %s: Externe Unterzeichner-Brieftasche wird geladen, ohne dass die Unterstützung für externe Unterzeichner kompiliert wurde</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Fehler: Adressbuchdaten im Wallet können nicht als zum migrierten Wallet zugehörig identifiziert werden</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Kann ungültige Datei peers.dat nicht umbenennen. Bitte Verschieben oder Löschen und noch einmal versuchen.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Konfigurationseinstellungen für %s sind nur auf %s network gültig, wenn in Sektion [%s]</translation>
</message>
@@ -671,10 +749,6 @@ Bitte nutzen Sie entweder "bdb" oder "sqlite".</translation>
<translation type="unfinished">Fehler beim Lesen des nächsten Eintrags aus der Wallet Datenbank</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Fehler bei der Aktualisierung einer Chainstate-Datenbank</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Fehler: Konnte den Cursor in der Datenbank nicht erzeugen</translation>
</message>
@@ -792,6 +866,10 @@ Berechnet: %s, erwartet: %s</translation>
<translation type="unfinished">Ungültige Netzmaske angegeben in -whitelist: '%s'</translation>
</message>
<message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">Das Abhören für eingehende Verbindungen ist fehlgeschlagen (Das Abhören hat Fehler %s zurückgegeben)</translation>
+ </message>
+ <message>
<source>Loading P2P addresses…</source>
<translation type="unfinished">Lade P2P-Adressen...</translation>
</message>
@@ -812,6 +890,10 @@ Berechnet: %s, erwartet: %s</translation>
<translation type="unfinished">Fehlender Betrag</translation>
</message>
<message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">Fehlende Auflösungsdaten zur Schätzung der Transaktionsgröße</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Angabe eines Ports benötigt für -whitebind: '%s'</translation>
</message>
@@ -820,10 +902,6 @@ Berechnet: %s, erwartet: %s</translation>
<translation type="unfinished">Keine Adressen verfügbar</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Kein Proxy-Server angegeben. Nutze -proxy=&lt;ip&gt; oder -proxy=&lt;ip:port&gt;.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Nicht genügend Datei-Deskriptoren verfügbar.</translation>
</message>
@@ -832,10 +910,6 @@ Berechnet: %s, erwartet: %s</translation>
<translation type="unfinished">Kürzungsmodus kann nicht mit einem negativen Wert konfiguriert werden.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Gekürzter "Prune" Modus ist mit -coinstatsindex nicht kompatibel.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Kürzungsmodus ist nicht mit -txindex kompatibel.</translation>
</message>
@@ -937,6 +1011,10 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Transaktionsbeträge dürfen nicht negativ sein.</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Ausgangsindex der Transaktionsänderung außerhalb des Bereichs</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">Die Speicherpoolkette der Transaktion ist zu lang.</translation>
</message>
@@ -945,10 +1023,18 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Die Transaktion muss mindestens einen Empfänger enthalten.</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Für die Transaktion wird eine neue Adresse benötigt, aber wir können sie nicht generieren.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Transaktion zu groß</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Speicher kann für -maxsigcachesize: '%s' MiB nicht zugewiesen werden:</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished">Kann auf diesem Computer nicht an %s binden (bind meldete Fehler %s)</translation>
</message>
@@ -973,6 +1059,10 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Unfähig %s zum Schreiben zu öffnen</translation>
</message>
<message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">Kann -maxuploadtarget: '%s' nicht parsen</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">Kann HTTP-Server nicht starten. Siehe Debug-Log für Details.</translation>
</message>
@@ -1001,10 +1091,6 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Nicht unterstützte Protokollkategorie %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Aktualisierung der UTXO-Datenbank</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Der User Agent Kommentar (%s) enthält unsichere Zeichen.</translation>
</message>
@@ -1223,8 +1309,8 @@ Verifikations-Error: %s</translation>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform> %n Blöcke der Transaktionshistorie verarbeitet.</numerusform>
+ <numerusform> %n Blöcke der Transaktionshistorie verarbeitet.</numerusform>
</translation>
</message>
<message>
@@ -1264,6 +1350,10 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Lade teilsignierte Bitcoin-Transaktion</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">PSBT von &amp;Zwischenablage laden...</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Lade teilsignierte Bitcoin-Transaktion aus Zwischenablage</translation>
</message>
@@ -1300,6 +1390,16 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Wallet schließen</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Wallet wiederherstellen...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Stelle eine Wallet aus einer Sicherungsdatei wieder her</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Schließe alle Wallets</translation>
</message>
@@ -1324,6 +1424,26 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Keine Wallets verfügbar</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Wallet-Daten</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Wallet Backup laden</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Wallet wiederherstellen</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Wallet-Name</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Programmfenster</translation>
</message>
@@ -1339,12 +1459,20 @@ Verifikations-Error: %s</translation>
<source>%1 client</source>
<translation type="unfinished">%1 Client</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Ausblenden</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">S&amp;Wie</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n aktive Verbindung(en) zum Bitcoin-Netzwerk.</numerusform>
+ <numerusform>%n aktive Verbindung(en) zum Bitcoin-Netzwerk.</numerusform>
</translation>
</message>
<message>
@@ -1433,7 +1561,7 @@ Verifikations-Error: %s</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation type="unfinished">Wallet ist &lt;b&gt;verschlüsselt&lt;/b&gt; und aktuell &lt;b&gt;entsperrt&lt;/b&gt;</translation>
+ <translation type="unfinished">Wallet ist &lt;b&gt;verschlüsselt&lt;/b&gt; und gerade &lt;b&gt;entsperrt&lt;/b&gt;.</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
@@ -1538,6 +1666,10 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Betrag kopieren</translation>
</message>
<message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Transaktion &amp;ID und Ausgabeindex kopieren</translation>
+ </message>
+ <message>
<source>L&amp;ock unspent</source>
<translation type="unfinished">Nicht ausgegebenen Betrag sperren</translation>
</message>
@@ -1626,6 +1758,10 @@ Verifikations-Error: %s</translation>
<source>Can't list signers</source>
<translation type="unfinished">Unterzeichner können nicht aufgelistet werden</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Zu viele externe Unterzeichner erkannt.</translation>
+ </message>
</context>
<context>
<name>LoadWalletsActivity</name>
@@ -1666,6 +1802,34 @@ Verifikations-Error: %s</translation>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Wallet wiederherstellen</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Wallet &lt;b&gt;%1&lt;/b&gt; wird wiederhergestellt ...</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Wallet Wiederherstellung fehlgeschlagen</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Wallet Wiederherstellungs Warnung</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Wallet Wiederherstellungs Nachricht</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1840,17 +2004,26 @@ Verifikations-Error: %s</translation>
</context>
<context>
<name>Intro</name>
- <message>
- <source>%1 GB of space available</source>
- <translation type="unfinished">%1 GB Speicherplatz verfügbar</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n GB Speicherplatz verfügbar</numerusform>
+ <numerusform>%n GB Speicherplatz verfügbar</numerusform>
+ </translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(von %1 GB benötigt)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(von %n GB benötigt)</numerusform>
+ <numerusform>(von %n GB benötigt)</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB benötigt für komplette Blockchain)</translation>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n GB benötigt für komplette Blockchain)</numerusform>
+ <numerusform>(%n GB benötigt für komplette Blockchain)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1864,8 +2037,8 @@ Verifikations-Error: %s</translation>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>(ausreichend um %n Tag(e) alte Backups wiederherzustellen)</numerusform>
+ <numerusform>(ausreichend um %n Tag(e) alte Backups wiederherzustellen)</numerusform>
</translation>
</message>
<message>
@@ -1897,10 +2070,6 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Da Sie das Programm gerade zum ersten Mal starten, können Sie nun auswählen wo %1 seine Daten ablegen wird.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Wenn Sie auf OK klicken, beginnt %1 mit dem Herunterladen und Verarbeiten der gesamten %4-Blockchain (%2GB), beginnend mit den frühesten Transaktionen in %3 beim ersten Start von %4.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Blockchain-Speicher beschränken auf</translation>
</message>
@@ -2005,7 +2174,7 @@ Verifikations-Error: %s</translation>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Unbekannt. Synchronisiere Headers (%1, %2%)...</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2061,6 +2230,10 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Minimiert die Anwendung anstatt sie zu beenden wenn das Fenster geschlossen wird. Wenn dies aktiviert ist, müssen Sie die Anwendung über "Beenden" im Menü schließen.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Einstellungen in diesem Dialog werden von der Kommandozeile überschrieben:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Öffnen Sie die %1 Konfigurationsdatei aus dem Arbeitsverzeichnis.</translation>
</message>
@@ -2089,10 +2262,25 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Wenn diese Einstellung rückgängig gemacht wird, muss die komplette Blockchain erneut heruntergeladen werden.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">Maximale Größe des Datenbank-Caches. Ein größerer Cache kann zu einer schnelleren Synchronisierung beitragen, danach ist der Vorteil für die meisten Anwendungsfälle weniger ausgeprägt. Eine Verringerung der Cache-Größe reduziert den Speicherverbrauch. Ungenutzter Mempool-Speicher wird für diesen Cache gemeinsam genutzt.</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Legen Sie die Anzahl der Skriptüberprüfungs-Threads fest. Negative Werte entsprechen der Anzahl der Kerne, die Sie für das System frei lassen möchten.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = automatisch, &lt;0 = so viele Kerne frei lassen)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Dies ermöglicht Ihnen oder einem Drittanbieter-Tool die Kommunikation mit dem Knoten über Befehlszeilen- und JSON-RPC-Befehle.</translation>
+ </message>
+ <message>
<source>Enable R&amp;PC server</source>
<extracomment>An Options window setting to enable the RPC server.</extracomment>
<translation type="unfinished">RPC-Server aktivieren</translation>
@@ -2102,6 +2290,16 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">B&amp;rieftasche</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Wählen Sie, ob die Gebühr standardmäßig vom Betrag abgezogen werden soll oder nicht.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Standardmäßig die Gebühr vom Betrag abziehen</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">Experten-Optionen</translation>
</message>
@@ -2118,6 +2316,16 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">&amp;Unbestätigtes Wechselgeld darf ausgegeben werden</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">&amp;PBST-Kontrollen aktivieren</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Ob PSBT-Kontrollen angezeigt werden sollen. </translation>
+ </message>
+ <message>
<source>External Signer (e.g. hardware wallet)</source>
<translation type="unfinished">Gerät für externe Signierung (z. B.: Hardware wallet)</translation>
</message>
@@ -2218,6 +2426,14 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Wählen Sie die standardmäßige Untereinheit, die in der Benutzeroberfläche und beim Überweisen von Bitcoins angezeigt werden soll.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">URLs von Drittanbietern (z. B. eines Block-Explorers), erscheinen als Kontextmenüpunkte auf der Registerkarte. 1%s in der URL wird durch den Transaktionshash ersetzt. Mehrere URLs werden durch senkrechte Striche | getrennt.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;Transaktions-URLs von Drittanbietern</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Legt fest, ob die "Coin Control"-Funktionen angezeigt werden.</translation>
</message>
@@ -2242,10 +2458,6 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">nächstliegende Übereinstimmung "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Einstellungen in diesem Dialog werden von der Kommandozeile oder in der Konfigurationsdatei überschrieben:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Abbrechen</translation>
</message>
@@ -2264,14 +2476,22 @@ Verifikations-Error: %s</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Zurücksetzen der Konfiguration bestätigen</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Client-Neustart erforderlich, um Änderungen zu aktivieren.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Aktuelle Einstellungen werden in "%1" gespeichert.</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Client wird beendet. Möchten Sie den Vorgang fortsetzen?</translation>
</message>
<message>
@@ -2310,6 +2530,13 @@ Verifikations-Error: %s</translation>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Die folgende Einstellung konnte nicht gelesen werden "%1", %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2419,6 +2646,10 @@ Verifikations-Error: %s</translation>
<translation type="unfinished">Signieren der Transaktion fehlgeschlagen: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Eingaben können nicht unterzeichnet werden, wenn die Brieftasche gesperrt ist.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">Konnte keinerlei weitere Eingaben signieren.</translation>
</message>
@@ -2560,6 +2791,11 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI
<translation type="unfinished">Gegenstelle</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Alter</translation>
+ </message>
+ <message>
<source>Sent</source>
<extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
<translation type="unfinished">Ãœbertragen</translation>
@@ -2747,17 +2983,33 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Ob wir Adressen an diese Gegenstelle weiterleiten.</translation>
</message>
<message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Adress-Relay</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Die Gesamtzahl der von dieser Gegenstelle empfangenen Adressen, die verarbeitet wurden (ausgenommen Adressen, die aufgrund von Ratenbegrenzung gelöscht wurden).</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Die Gesamtzahl der von dieser Gegenstelle empfangenen Adressen, die aufgrund von Ratenbegrenzung verworfen (nicht verarbeitet) wurden.</translation>
+ </message>
+ <message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">Verarbeitete Adressen</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">Gesamtzahl der Adressen, die wegen Ratenbeschränkungen verworfen wurden.</translation>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Ratenbeschränkte Adressen</translation>
</message>
<message>
<source>User Agent</source>
@@ -2985,6 +3237,10 @@ Wenn Sie diese Fehlermeldung erhalten, sollten Sie den Händler bitten, einen BI
<translation type="unfinished">Befehl wird ohne spezifizierte Wallet ausgeführt</translation>
</message>
<message>
+ <source>Ctrl+T</source>
+ <translation type="unfinished">Ctrl+T </translation>
+ </message>
+ <message>
<source>Executing command using "%1" wallet</source>
<translation type="unfinished">Befehl wird mit Wallet "%1" ausgeführt</translation>
</message>
@@ -3506,6 +3762,11 @@ Hinweis: Da die Gebühr auf Basis der Bytes berechnet wird, führt eine Gebühre
<translation type="unfinished">Möchtest du diese Transaktion erstellen?</translation>
</message>
<message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Bitte überprüfen Sie Ihre Transaktion. Sie können diese Transaktion erstellen und versenden oder eine Partially Signed Bitcoin Transaction (PSBT) erstellen, die Sie speichern oder kopieren und dann z.B. mit einer offline %1 Wallet oder einer PSBT-kompatiblen Hardware-Wallet signieren können.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Bitte überprüfen sie ihre Transaktion.</translation>
@@ -3558,15 +3819,11 @@ Hinweis: Da die Gebühr auf Basis der Bytes berechnet wird, führt eine Gebühre
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Eine höhere Gebühr als %1 wird als unsinnig hohe Gebühr angesehen.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Zahlungsanforderung abgelaufen.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Voraussichtlicher Beginn der Bestätigung innerhalb von %n Blöcken.</numerusform>
+ <numerusform>Voraussichtlicher Beginn der Bestätigung innerhalb von %n Blöcken.</numerusform>
</translation>
</message>
<message>
@@ -3641,14 +3898,6 @@ Hinweis: Da die Gebühr auf Basis der Bytes berechnet wird, führt eine Gebühre
<translation type="unfinished">Nachricht:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Dies ist keine beglaubigte Zahlungsanforderung.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Dies ist eine beglaubigte Zahlungsanforderung.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Adressbezeichnung eingeben, die dann zusammen mit der Adresse der Liste bereits verwendeter Adressen hinzugefügt wird.</translation>
</message>
@@ -3656,11 +3905,7 @@ Hinweis: Da die Gebühr auf Basis der Bytes berechnet wird, führt eine Gebühre
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Eine an die "bitcoin:"-URI angefügte Nachricht, die zusammen mit der Transaktion gespeichert wird. Hinweis: Diese Nachricht wird nicht über das Bitcoin-Netzwerk gesendet.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Empfänger:</translation>
- </message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -3817,35 +4062,41 @@ Hinweis: Da die Gebühr auf Basis der Bytes berechnet wird, führt eine Gebühre
<source>(press q to shutdown and continue later)</source>
<translation type="unfinished">(drücke q, um herunterzufahren und später fortzuführen)</translation>
</message>
- </context>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">q zum Herunterfahren drücken</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">steht im Konflikt mit einer Transaktion mit %1 Bestätigungen</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/unbestätigt, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">im Speicher-Pool</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/unbestätigt, im Speicherpool</translation>
</message>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">nicht im Speicher-Pool</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/unbestätigt, nicht im Speicherpool</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">eingestellt</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/unbestätigt</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 Bestätigungen</translation>
</message>
<message>
@@ -4189,6 +4440,11 @@ Hinweis: Da die Gebühr auf Basis der Bytes berechnet wird, führt eine Gebühre
<translation type="unfinished">Adressbezeichnung bearbeiten</translation>
</message>
<message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Zeige in %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Transaktionsverlauf exportieren</translation>
</message>
diff --git a/src/qt/locale/bitcoin_el.ts b/src/qt/locale/bitcoin_el.ts
index b581c8baca..9c38fd0d0e 100644
--- a/src/qt/locale/bitcoin_el.ts
+++ b/src/qt/locale/bitcoin_el.ts
@@ -242,6 +242,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Το αÏχείο Ρυθμίσεων %1 ενδέχεται να είναι κατεστÏαμμένο ή μη έγκυÏο.</translation>
+ </message>
+ <message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
<translation type="unfinished">Συνέβη ενα μοιÏαίο σφάλμα. %1 δε μποÏεί να συνεχιστεί με ασφάλεια και θα σταματήσει</translation>
</message>
@@ -328,6 +332,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ΧειÏοκίνητα</translation>
</message>
<message>
+ <source>Address Fetch</source>
+ <extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
+ <translation type="unfinished">Λήψη ΔιεÏθυνσης</translation>
+ </message>
+ <message>
<source>None</source>
<translation type="unfinished">Κανένα</translation>
</message>
@@ -429,10 +438,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Σφάλμα: Η έκδοση του αÏχείου dump δεν υποστηÏίζεται. Αυτή η έκδοση του bitcoin-wallet υποστηÏίζει αÏχεία dump μόνο της έκδοσης 1. Δόθηκε αÏχείο dump έκδοσης %s.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Σφάλμα: Η ακÏόαση για εισεÏχόμενες συνδέσεις απέτυχε (ακοÏστε επιστÏαμμένο σφάλμα %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Η αποτίμηση του τέλους απέτυχε. Το Fallbackfee είναι απενεÏγοποιημένο. ΠεÏιμένετε λίγα τετÏάγωνα ή ενεÏγοποιήστε το -fallbackfee.</translation>
</message>
@@ -473,6 +478,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Κλάδεμα: ο τελευταίος συγχÏονισμός ποÏÏ„Î¿Ï†Î¿Î»Î¹Î¿Ï Î¾ÎµÏ€ÎµÏνά τα κλαδεμένα δεδομένα. ΠÏέπει να κάνετε -reindex (κατεβάστε ολόκληÏο το blockchain και πάλι σε πεÏίπτωση κλαδέματος κόμβου)</translation>
</message>
<message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation type="unfinished">SQLiteDatabase: Άγνωστη sqlite έκδοση %d του schema ποÏÏ„Î¿Ï†Î¿Î»Î¹Î¿Ï . ΥποστηÏίζεται μόνο η έκδοση %d.</translation>
+ </message>
+ <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation type="unfinished">Η βάση δεδομένων μπλοκ πεÏιέχει ένα μπλοκ που φαίνεται να είναι από το μέλλον. Αυτό μποÏεί να οφείλεται στην εσφαλμένη ÏÏθμιση της ημεÏομηνίας και της ÏŽÏας του υπολογιστή σας. Αποκαταστήστε μόνο τη βάση δεδομένων μπλοκ αν είστε βέβαιοι ότι η ημεÏομηνία και η ÏŽÏα του υπολογιστή σας είναι σωστές</translation>
</message>
@@ -601,10 +610,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Σφάλμα ανάγνωσης από τη βάση δεδομένων, εκτελείται τεÏματισμός.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Σφάλμα κατά την αναβάθμιση της βάσης δεδομένων chainstate</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Σφάλμα: Ο χώÏος στο δίσκο είναι χαμηλός για %s</translation>
</message>
@@ -705,8 +710,8 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ΠÏέπει να καθοÏίσετε μια θÏÏα με -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Δεν οÏίστηκε διακομιστής μεσολάβησης. ΧÏησιμοποιήστε -proxy=&lt;ip&gt; ή -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Καμμία διαθέσιμη διεÏθυνση</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -729,6 +734,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ΣάÏωση εκ νέου...</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation type="unfinished">SQLite βάση δεδομένων: Απέτυχε η εκτέλεση της δήλωσης για την επαλήθευση της βάσης δεδομένων: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation type="unfinished">SQLite βάση δεδομένων: Απέτυχε η Ï€Ïοετοιμασία της δήλωσης για την επαλήθευση της βάσης δεδομένων: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation type="unfinished">SQLite βάση δεδομένων: Απέτυχε η ανάγνωση της επαλήθευσης του σφάλματος της βάσης δεδομένων: %s</translation>
+ </message>
+ <message>
<source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
<translation type="unfinished">SQLiteDatabase: Μη αναμενόμενο αναγνωÏιστικό εφαÏμογής. Αναμενόταν: %u, ελήφθη: %u</translation>
</message>
@@ -757,6 +774,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Δεν υπάÏχει κατάλογος καθοÏισμένων μπλοκ "%s".</translation>
</message>
<message>
+ <source>Starting network threads…</source>
+ <translation type="unfinished">Εκκίνηση των threads δικτÏου...</translation>
+ </message>
+ <message>
<source>The source code is available from %s.</source>
<translation type="unfinished"> Ο πηγαίος κώδικας είναι διαθέσιμος από το %s.</translation>
</message>
@@ -845,18 +866,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Έχει οÏιστεί άγνωστo δίκτυο στο -onlynet: '%s'</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">Μη υποστηÏιζόμενη κατηγοÏία καταγÏαφής %s=%s.</translation>
+ <source>Unknown new rules activated (versionbit %i)</source>
+ <translation type="unfinished">ΕνεÏγοποιήθηκαν άγνωστοι νέοι κανόνες (bit έκδοσης %i)</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Αναβάθμιση της βάσης δεδομένων UTXO</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Μη υποστηÏιζόμενη κατηγοÏία καταγÏαφής %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Το σχόλιο του παÏάγοντα χÏήστη (%s) πεÏιέχει μη ασφαλείς χαÏακτήÏες.</translation>
</message>
<message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">Επαλήθευση των blocks…</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)…</source>
<translation type="unfinished">Επαλήθευση ποÏτοφολιοÏ/ιών...</translation>
</message>
@@ -986,7 +1011,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation type="unfinished">Ελέγξτε τα μηνÏματα για να βεβαιωθείτε ότι υπογÏάφηκαν με τις καθοÏισμένες διευθÏνσεις Bitcoin</translation>
+ <translation type="unfinished">ΥπογÏάψτε ένα μήνυμα για ν' αποδείξετε πως ανήκει μια συγκεκÏιμένη διεÏθυνση Bitcoin</translation>
</message>
<message>
<source>&amp;Load PSBT from file…</source>
@@ -1067,8 +1092,8 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>ΕπεξεÏγάστηκε %n των μπλοκ του ιστοÏÎ¹ÎºÎ¿Ï ÏƒÏ…Î½Î±Î»Î»Î±Î³ÏŽÎ½.</numerusform>
+ <numerusform>ΕπεξεÏγάσθηκαν %n μπλοκ του ιστοÏÎ¹ÎºÎ¿Ï ÏƒÏ…Î½Î±Î»Î»Î±Î³ÏŽÎ½.</numerusform>
</translation>
</message>
<message>
@@ -1148,6 +1173,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Κλείσιμο ποÏτοφολιοÏ</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">ΕπαναφοÏά ΠοÏτοφολιοÏ...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">ΕπαναφοÏά ενός ποÏÏ„Î¿Ï†Î¿Î»Î¹Î¿Ï Î±Ï€ÏŒ ένα αÏχείο αντίγÏαφου ασφαλείας</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Κλείσιμο όλων των ποÏτοφολιών</translation>
</message>
@@ -1172,6 +1207,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Κανένα ποÏτοφόλι διαθέσιμο</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Δεδομένα ποÏτοφολιοÏ</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">ΦόÏτωση ΑντίγÏαφου Ασφαλείας ΠοÏτοφολιοÏ</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">ΕπαναφοÏά ΠοÏτοφολιοÏ</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Όνομα ΠοÏτοφολιοÏ</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;ΠαÏάθυÏο</translation>
</message>
@@ -1187,12 +1242,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 πελάτης</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">$ΑπόκÏυψη</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">Ε&amp;μφάνιση</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>1%n ενεÏγές συνδέσεις στο δίκτυο Bitcoin.</numerusform>
+ <numerusform>%n ενεÏγές συνδέσεις στο δίκτυο Bitcoin.</numerusform>
</translation>
</message>
<message>
@@ -1390,6 +1453,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">L&amp;ock διαθέσιμο</translation>
</message>
<message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">&amp;Ξεκλείδωμα διαθέσιμου υπολοίπου</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">ΑντιγÏαφή ποσότητας</translation>
</message>
@@ -1470,7 +1537,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">Αδυναμία απαÏίθμησης εγγεγÏαμμένων </translation>
</message>
-</context>
+ </context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1510,6 +1577,34 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">ΕπαναφοÏά ΠοÏτοφολιοÏ</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">ΕπαναφοÏά ΠοÏÏ„Î¿Ï†Î¿Î»Î¹Î¿Ï &lt;b&gt; %1 &lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Αποτυχία επαναφοÏάς ποÏτοφολιοÏ</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">ΠÏοειδοποίηση επαναφοÏάς ποÏτοφολιοÏ</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">ÎœÏνημα επαναφοÏάς ποÏτοφολιοÏ</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1583,6 +1678,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ΠοÏτοφόλι ΠεÏιγÏαφέα </translation>
</message>
<message>
+ <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
+ <translation type="unfinished">ΧÏησιμοποιήστε μια εξωτεÏική συσκευή υπογÏαφής, όπως ένα ποÏτοφόλι υλικοÏ. Ρυθμίστε Ï€Ïώτα στις Ï€Ïοτιμήσεις του ποÏÏ„Î¿Ï†Î¿Î»Î¹Î¿Ï Ï„Î¿ εξωτεÏικό script υπογÏαφής.</translation>
+ </message>
+ <message>
<source>External signer</source>
<translation type="unfinished">ΕξωτεÏικός υπογÏάφων</translation>
</message>
@@ -1594,7 +1693,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Compiled without sqlite support (required for descriptor wallets)</source>
<translation type="unfinished">Μεταγλωτίστηκε χωÏίς την υποστήÏιξη sqlite (απαÏαίτητη για πεÏιγÏαφικά ποÏτοφόλια )</translation>
</message>
- </context>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Συντάχθηκε χωÏίς την υποστήÏιξη εξωτεÏικής υπογÏαφής (απαιτείται για εξωτεÏική υπογÏαφή)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -1675,13 +1779,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(από τα %1 GB που απαιτοÏνται)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB απαιτοÏνται για την πλήÏη αλυσίδα)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1724,10 +1841,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ΚαλωσήÏθες στο %1.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Όταν κάνετε κλικ στο OK, το %1 θα ξεκινήσει τη λήψη και την επεξεÏγασία της πλήÏους αλυσίδας μπλοκ% 4 (%2GB) αÏχίζοντας από τις Ï€Ïώτες συναλλαγές στο %3 όταν αÏχικά ξεκίνησε το %4.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">ΠεÏιόÏισε την χωÏητικότητα της αλυσίδας block σε</translation>
</message>
@@ -1836,7 +1949,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Άγνωστο. ΣυγχÏονισμός επικεφαλίδων (%1, %2%)...</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -1888,6 +2001,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ελαχιστοποίηση αντί για έξοδο κατά το κλείσιμο του παÏαθÏÏου. Όταν αυτή η επιλογή είναι ενεÏγοποιημένη, η εφαÏμογή θα κλείνει μόνο αν επιλεχθεί η Έξοδος στο μενοÏ.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Οι επιλογές που έχουν οÏιστεί σε αυτό το παÏάθυÏο διαλόγου παÏαβλέπονται από τη γÏαμμή εντολών</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Ανοίξτε το %1 αÏχείο διαμόÏφωσης από τον κατάλογο εÏγασίας.</translation>
</message>
@@ -1924,6 +2041,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">(0 = αυτόματο, &lt;0 = ελεÏθεÏοι πυÏήνες)</translation>
</message>
<message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">ΕνεÏγοποίηση R&amp;PC σέÏβεÏ</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">Π&amp;οÏτοφόλι</translation>
</message>
@@ -1944,6 +2066,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Ξόδεμα μη επικυÏωμένων Ïέστων</translation>
</message>
<message>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">ΕξωτεÏική συσκευή υπογÏαφής (Ï€.χ. ποÏτοφόλι υλικοÏ)</translation>
+ </message>
+ <message>
<source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
<translation type="unfinished">ΠλήÏης διαδÏομή ενός script ÏƒÏ…Î¼Î²Î±Ï„Î¿Ï Î¼Îµ το Bitcoin Core (Ï€.χ.: C:\Downloads\hwi.exe ή /Users/you/Downloads/hwi.py). ΠÏοσοχή: το κακόβουλο λογισμικό μποÏεί να κλέψει τα νομίσματά σας!</translation>
</message>
@@ -1956,6 +2082,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Απόδοση θυÏών με χÏήση &amp;UPnP</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Ανοίξτε αυτόματα τη πόÏτα του Bitcoin client στο router. Αυτό λειτουÏγεί μόνο όταν το router σας υποστηÏίζει NAT-PMP και είναι ενεÏγοποιημένο. Η εξωτεÏική πόÏτα μποÏεί να είναι τυχαία.</translation>
+ </message>
+ <message>
<source>Map port using NA&amp;T-PMP</source>
<translation type="unfinished">ΔÏομολόγηση θÏÏας με χÏήση NA&amp;T-PMP</translation>
</message>
@@ -2052,8 +2182,8 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ενσωματωμένο "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Οι επιλογές που έχουν οÏιστεί σε αυτό το παÏάθυÏο διαλόγου παÏαβλέπονται από τη γÏαμμή εντολών ή από το αÏχείο διαμόÏφωσης:</translation>
+ <source>closest matching "%1"</source>
+ <translation type="unfinished">πλησιέστεÏη αντιστοίχιση "%1"</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -2064,6 +2194,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;ΑκÏÏωση</translation>
</message>
<message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Συντάχθηκε χωÏίς την υποστήÏιξη εξωτεÏικής υπογÏαφής (απαιτείται για εξωτεÏική υπογÏαφή)</translation>
+ </message>
+ <message>
<source>default</source>
<translation type="unfinished">Ï€Ïοεπιλογή</translation>
</message>
@@ -2073,14 +2208,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Επιβεβαίωση επαναφοÏάς επιλογών</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">ΧÏειάζεται επανεκκίνηση του Ï€ÏογÏάμματος για να ενεÏγοποιηθοÏν οι αλλαγές.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Ο πελάτης θα τεÏματιστεί. Θέλετε να συνεχίσετε?</translation>
</message>
<message>
@@ -2095,6 +2233,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Το αÏχείο Ïυθμίσεων χÏησιμοποιείται για τον Ï€ÏοσδιοÏισμό των Ï€ÏοχωÏημένων επιλογών χÏηστών που παÏακάμπτουν τις Ïυθμίσεις GUI. Επιπλέον, όλες οι επιλογές γÏαμμής εντολών θα αντικαταστήσουν αυτό το αÏχείο Ïυθμίσεων.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">Συνεχίστε</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">ΑκÏÏωση</translation>
</message>
@@ -2116,6 +2258,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Δεν μποÏεί να διαβαστεί η ÏÏθμιση "%1", %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2303,6 +2452,10 @@ ID Συναλλαγής: %1</translation>
<translation type="unfinished">Η συναλλαγή απαιτεί υπογÏαφή/ές</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Δεν έχει γίνει φόÏτωση ποÏτοφολιοÏ)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Αλλά αυτό το ποÏτοφόλι δεν μποÏεί να υπογÏάψει συναλλαγές.)</translation>
</message>
@@ -2359,6 +2512,11 @@ ID Συναλλαγής: %1</translation>
<translation type="unfinished">ΧÏήστης</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Ηλικία</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">ΚατεÏθυνση</translation>
@@ -2542,6 +2700,10 @@ ID Συναλλαγής: %1</translation>
<translation type="unfinished">ΣυγχÏονισμένα Μπλοκς</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Τελευταία Συναλλαγή</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">Το χαÏτογÏαφημένο Αυτόνομο ΣÏστημα που χÏησιμοποιείται για τη διαφοÏοποίηση της επιλογής ομοτίμων.</translation>
</message>
@@ -2598,6 +2760,10 @@ ID Συναλλαγής: %1</translation>
<translation type="unfinished">ΧÏόνος σÏνδεσης</translation>
</message>
<message>
+ <source>Last Block</source>
+ <translation type="unfinished">Τελευταίο Block</translation>
+ </message>
+ <message>
<source>Last Send</source>
<translation type="unfinished">Τελευταία αποστολή</translation>
</message>
@@ -2662,6 +2828,11 @@ ID Συναλλαγής: %1</translation>
<translation type="unfinished">ΕξεÏχόμενα:</translation>
</message>
<message>
+ <source>Inbound: initiated by peer</source>
+ <extracomment>Explanatory text for an inbound peer connection.</extracomment>
+ <translation type="unfinished">ΕισεÏχόμενo: Ξεκίνησε από peer</translation>
+ </message>
+ <message>
<source>the peer selected us for high bandwidth relay</source>
<translation type="unfinished">ο ομότιμος μας επέλεξε για υψηλής ταχÏτητας αναμετάδοση </translation>
</message>
@@ -2687,6 +2858,11 @@ ID Συναλλαγής: %1</translation>
<translation type="unfinished">1 &amp;χÏόνος</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">&amp;ΑντιγÏαφή IP/Netmask</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">&amp;ΑκÏÏωση ΑπαγόÏευσης</translation>
</message>
@@ -2699,6 +2875,10 @@ ID Συναλλαγής: %1</translation>
<translation type="unfinished">Εκτέλεση εντολής χωÏίς ποÏτοφόλι</translation>
</message>
<message>
+ <source>Ctrl+I</source>
+ <translation type="unfinished">Ctrl+Ι </translation>
+ </message>
+ <message>
<source>Executing command using "%1" wallet</source>
<translation type="unfinished"> 
Εκτελέστε εντολή χÏησιμοποιώντας το ποÏτοφόλι "%1"</translation>
@@ -3139,6 +3319,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">%1 Ï€Ïος το %2</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details…"</source>
+ <translation type="unfinished">Για να αναθεωÏήσετε τη λίστα παÏαληπτών, κάντε κλικ στην επιλογή "Εμφάνιση λεπτομεÏειών..."</translation>
+ </message>
+ <message>
<source>Sign failed</source>
<translation type="unfinished">H εγγÏαφή απέτυχε</translation>
</message>
@@ -3161,6 +3345,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">Το PSBT αποθηκεÏτηκε</translation>
</message>
<message>
+ <source>External balance:</source>
+ <translation type="unfinished">ΕξωτεÏικό υπόλοιπο:</translation>
+ </message>
+ <message>
<source>or</source>
<translation type="unfinished">ή</translation>
</message>
@@ -3174,6 +3362,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">ΠαÏακαλοÏμε, ελέγξτε την Ï€Ïόταση συναλλαγής. Θα παÏαχθεί μια συναλλαγή Bitcoin με μεÏική υπογÏαφή (PSBT), την οποία μποÏείτε να αντιγÏάψετε και στη συνέχεια να υπογÏάψετε με Ï€.χ. ένα ποÏτοφόλι %1 εκτός σÏνδεσης ή ένα ποÏτοφόλι Ï…Î»Î¹ÎºÎ¿Ï ÏƒÏ…Î¼Î²Î±Ï„ÏŒ με το PSBT.</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Θέλετε να δημιουÏγήσετε αυτήν τη συναλλαγή;</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">ΠαÏακαλοÏμε, ελέγξτε τη συναλλαγή σας.</translation>
@@ -3227,10 +3420,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Ένα τέλος υψηλότεÏο από το %1 θεωÏείται ένα παÏάλογο υψηλό έξοδο.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Η αίτηση πληÏωμής έληξε.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3306,14 +3495,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">Μήνυμα:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">ΠÏόκειται για αίτημα πληÏωμής χωÏίς έλεγχο ταυτότητας.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">ΠÏόκειται για ένα πιστοποιημένο αίτημα πληÏωμής.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Εισάγετε μία ετικέτα για αυτή την διεÏθυνση για να Ï€Ïοστεθεί στη λίστα με τις χÏησιμοποιημένες διευθÏνσεις</translation>
</message>
@@ -3321,14 +3502,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Ένα μήνυμα που επισυνάφθηκε στο bitcoin: URI το οποίο θα αποθηκευτεί με τη συναλλαγή για αναφοÏά. Σημείωση: Αυτό το μήνυμα δεν θα σταλεί μέσω του δικτÏου Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">ΠληÏωμή σε:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Σημείωση:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3485,33 +3658,36 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
</context>
<context>
- <name>TransactionDesc</name>
+ <name>SplashScreen</name>
<message>
- <source>conflicted with a transaction with %1 confirmations</source>
- <translation type="unfinished">σε σÏγκÏουση με μια συναλλαγή με %1 επιβεβαιώσεις</translation>
+ <source>(press q to shutdown and continue later)</source>
+ <translation type="unfinished">(πατήστε q για κλείσιμο και συνεχίστε αÏγότεÏα)</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/ανεπιβεβαίωτο, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">στην πισίνα μνήμης</translation>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">πατήστε q για κλείσιμο</translation>
</message>
+</context>
+<context>
+ <name>TransactionDesc</name>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">όχι στην πισίνα μνήμης</translation>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
+ <translation type="unfinished">σε σÏγκÏουση με μια συναλλαγή με %1 επιβεβαιώσεις</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">εγκαταλελειμμένος</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/μη επιβεβαιωμένο</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 επιβεβαιώσεις</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 35d8201877..586240445e 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -55,7 +55,7 @@
</message>
<message>
<location line="-30"/>
- <location filename="../addressbookpage.cpp" line="+122"/>
+ <location filename="../addressbookpage.cpp" line="+128"/>
<source>&amp;Delete</source>
<translation>&amp;Delete</translation>
</message>
@@ -313,7 +313,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>BitcoinApplication</name>
<message>
- <location filename="../bitcoin.cpp" line="+433"/>
+ <location filename="../bitcoin.cpp" line="+288"/>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+178"/>
<source>Runaway exception</source>
<translation type="unfinished"></translation>
</message>
@@ -336,7 +341,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+250"/>
+ <location filename="../bitcoingui.cpp" line="+253"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -396,7 +401,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+127"/>
+ <location line="+160"/>
<source>&amp;Minimize</source>
<translation type="unfinished"></translation>
</message>
@@ -406,18 +411,18 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+392"/>
+ <location line="+393"/>
<source>Network activity disabled.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+422"/>
+ <location line="+439"/>
<source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1109"/>
+ <location line="-1160"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -507,17 +512,17 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+10"/>
<source>Close All Wallets…</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+94"/>
+ <location line="+119"/>
<source>&amp;File</source>
<translation>&amp;File</translation>
</message>
<message>
- <location line="+18"/>
+ <location line="+20"/>
<source>&amp;Settings</source>
<translation>&amp;Settings</translation>
</message>
@@ -532,12 +537,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Tabs toolbar</translation>
</message>
<message>
- <location line="+456"/>
+ <location line="+457"/>
<source>Syncing Headers (%1%)…</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+47"/>
+ <location line="+58"/>
<source>Synchronizing with network…</source>
<translation type="unfinished"></translation>
</message>
@@ -562,7 +567,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-788"/>
+ <location line="-833"/>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished"></translation>
</message>
@@ -577,12 +582,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+20"/>
+ <location line="+26"/>
<source>&amp;Command-line options</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location line="+710"/>
+ <location line="+749"/>
<source>Processed %n block(s) of transaction history.</source>
<translation>
<numerusform>Processed %n block of transaction history.</numerusform>
@@ -630,7 +635,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Up to date</translation>
</message>
<message>
- <location line="-747"/>
+ <location line="-818"/>
+ <source>Ctrl+Q</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+26"/>
<source>Load Partially Signed Bitcoin Transaction</source>
<translation type="unfinished"></translation>
</message>
@@ -686,6 +696,18 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</message>
<message>
<location line="+7"/>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Close all wallets</source>
<translation type="unfinished"></translation>
</message>
@@ -715,12 +737,41 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+63"/>
+ <location line="+6"/>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+71"/>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Window</translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+3"/>
+ <source>Ctrl+M</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+9"/>
<source>Zoom</source>
<translation type="unfinished"></translation>
</message>
@@ -730,7 +781,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+257"/>
+ <location line="+258"/>
<source>%1 client</source>
<translation type="unfinished"></translation>
</message>
@@ -778,7 +829,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+158"/>
+ <location line="+17"/>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+152"/>
<source>Error: %1</source>
<translation type="unfinished"></translation>
</message>
@@ -849,7 +905,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+23"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</translation>
</message>
@@ -1022,7 +1078,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+155"/>
+ <location line="+154"/>
<source>yes</source>
<translation type="unfinished"></translation>
</message>
@@ -1061,7 +1117,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>CreateWalletActivity</name>
<message>
- <location filename="../walletcontroller.cpp" line="+243"/>
+ <location filename="../walletcontroller.cpp" line="+244"/>
<source>Create Wallet</source>
<extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
<translation type="unfinished"></translation>
@@ -1073,7 +1129,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+29"/>
+ <location line="+33"/>
<source>Create wallet failed</source>
<translation type="unfinished"></translation>
</message>
@@ -1087,6 +1143,11 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<source>Can&apos;t list signers</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location line="+3"/>
+ <source>Too many external signers found</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>CreateWalletDialog</name>
@@ -1276,7 +1337,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>HelpMessageDialog</name>
<message>
- <location filename="../utilitydialog.cpp" line="+37"/>
+ <location filename="../utilitydialog.cpp" line="+38"/>
<source>version</source>
<translation type="unfinished">version</translation>
</message>
@@ -1286,7 +1347,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+18"/>
<source>Command-line options</source>
<translation type="unfinished"></translation>
</message>
@@ -1309,12 +1370,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+157"/>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+32"/>
+ <location line="+189"/>
<source>Limit block chain storage to</source>
<translation type="unfinished"></translation>
</message>
@@ -1334,7 +1390,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="-10"/>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+20"/>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished"></translation>
</message>
@@ -1353,20 +1414,29 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<source>Bitcoin</source>
<translation type="unfinished">Bitcoin</translation>
</message>
- <message>
+ <message numerus="yes">
<location line="+162"/>
- <source>%1 GB of space available</source>
- <translation type="unfinished"></translation>
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
- <message>
+ <message numerus="yes">
<location line="+2"/>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished"></translation>
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
- <message>
+ <message numerus="yes">
<location line="+3"/>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished"></translation>
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform></numerusform>
+ <numerusform></numerusform>
+ </translation>
</message>
<message>
<location line="+72"/>
@@ -1411,7 +1481,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>LoadWalletsActivity</name>
<message>
- <location filename="../walletcontroller.cpp" line="+69"/>
+ <location filename="../walletcontroller.cpp" line="+74"/>
<source>Load Wallets</source>
<extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
<translation type="unfinished"></translation>
@@ -1448,7 +1518,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<message>
<location line="+7"/>
<location line="+26"/>
- <location filename="../modaloverlay.cpp" line="+152"/>
+ <location filename="../modaloverlay.cpp" line="+155"/>
<source>Unknown…</source>
<translation type="unfinished"></translation>
</message>
@@ -1489,15 +1559,20 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../modaloverlay.cpp" line="-118"/>
+ <location filename="../modaloverlay.cpp" line="-121"/>
<source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+124"/>
+ <location line="+127"/>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location line="+5"/>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1521,7 +1596,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>OpenWalletActivity</name>
<message>
- <location filename="../walletcontroller.cpp" line="-42"/>
+ <location filename="../walletcontroller.cpp" line="-46"/>
<source>Open wallet failed</source>
<translation type="unfinished"></translation>
</message>
@@ -1604,7 +1679,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+272"/>
+ <location line="+227"/>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+45"/>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished"></translation>
</message>
@@ -1916,12 +1996,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+65"/>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+141"/>
+ <location line="+206"/>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1931,7 +2006,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>&amp;Cancel</translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="+99"/>
+ <location filename="../optionsdialog.cpp" line="+96"/>
<source>Compiled without external signing support (required for external signing)</source>
<extracomment>&quot;External signing&quot; means using devices such as hardware wallets.</extracomment>
<translation type="unfinished"></translation>
@@ -1942,28 +2017,37 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>default</translation>
</message>
<message>
- <location line="+81"/>
+ <location line="+86"/>
<source>none</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+97"/>
+ <location line="+107"/>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation>Confirm options reset</translation>
</message>
<message>
- <location line="+1"/>
- <location line="+70"/>
+ <location line="-9"/>
+ <location line="+79"/>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-75"/>
+ <source>Current settings will be backed up at &quot;%1&quot;.</source>
+ <extracomment>Text explaining to the user that the client&apos;s current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location&apos;s path.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-70"/>
+ <location line="+3"/>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+18"/>
+ <location line="+20"/>
<source>Configuration options</source>
<extracomment>Window title text of pop-up box that allows opening up of configuration file.</extracomment>
<translation type="unfinished"></translation>
@@ -2006,6 +2090,14 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <location filename="../optionsmodel.cpp" line="+204"/>
+ <source>Could not read setting &quot;%1&quot;, %2.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<location filename="../forms/overviewpage.ui" line="+14"/>
@@ -2099,7 +2191,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../overviewpage.cpp" line="+187"/>
+ <location filename="../overviewpage.cpp" line="+185"/>
<source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
<translation type="unfinished"></translation>
</message>
@@ -2271,7 +2363,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>PaymentServer</name>
<message>
- <location filename="../paymentserver.cpp" line="+173"/>
+ <location filename="../paymentserver.cpp" line="+152"/>
<source>Payment request error</source>
<translation type="unfinished"></translation>
</message>
@@ -2281,7 +2373,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+50"/>
+ <location line="+48"/>
<location line="+16"/>
<location line="+6"/>
<location line="+7"/>
@@ -2315,7 +2407,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<context>
<name>PeerTableModel</name>
<message>
- <location filename="../peertablemodel.h" line="+108"/>
+ <location filename="../peertablemodel.h" line="+112"/>
<source>User Agent</source>
<extracomment>Title of Peers Table column which contains the peer&apos;s User Agent string.</extracomment>
<translation type="unfinished"></translation>
@@ -2327,12 +2419,18 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-15"/>
+ <location line="-18"/>
<source>Peer</source>
<extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+3"/>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+6"/>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
@@ -2369,7 +2467,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">Network</translation>
</message>
<message>
- <location filename="../peertablemodel.cpp" line="+79"/>
+ <location filename="../peertablemodel.cpp" line="+78"/>
<source>Inbound</source>
<extracomment>An Inbound Connection from a Peer.</extracomment>
<translation type="unfinished"></translation>
@@ -2384,17 +2482,22 @@ If you are receiving this error you should request the merchant provide a BIP21
<context>
<name>QObject</name>
<message>
- <location filename="../bitcoinunits.cpp" line="+215"/>
+ <location filename="../bitcoinunits.cpp" line="+197"/>
<source>Amount</source>
<translation type="unfinished">Amount</translation>
</message>
<message>
- <location filename="../guiutil.cpp" line="+127"/>
+ <location filename="../guiutil.cpp" line="+129"/>
<source>Enter a Bitcoin address (e.g. %1)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+546"/>
+ <location line="+288"/>
+ <source>Ctrl+W</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+256"/>
<source>Unroutable</source>
<translation type="unfinished"></translation>
</message>
@@ -2446,23 +2549,27 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+15"/>
+ <location line="+13"/>
+ <location line="+12"/>
<source>%1 d</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="-11"/>
+ <location line="+12"/>
<source>%1 h</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="-11"/>
+ <location line="+12"/>
<source>%1 m</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
- <location line="+28"/>
+ <location line="-10"/>
+ <location line="+11"/>
+ <location line="+26"/>
<source>%1 s</source>
<translation type="unfinished"></translation>
</message>
@@ -2556,7 +2663,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="-276"/>
+ <location filename="../bitcoin.cpp" line="-294"/>
<source>Do you want to reset settings to default values, or to abort without making changes?</source>
<extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
<translation type="unfinished"></translation>
@@ -2568,7 +2675,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+373"/>
+ <location line="+393"/>
<source>Error: Specified data directory &quot;%1&quot; does not exist.</source>
<translation type="unfinished"></translation>
</message>
@@ -2583,12 +2690,12 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+71"/>
+ <location line="+74"/>
<source>%1 didn&apos;t yet exit safely…</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../modaloverlay.cpp" line="-35"/>
+ <location filename="../modaloverlay.cpp" line="-40"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
@@ -2672,7 +2779,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<location line="+26"/>
<location line="+26"/>
<location line="+26"/>
- <location filename="../rpcconsole.h" line="+139"/>
+ <location filename="../rpcconsole.h" line="+143"/>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -2791,7 +2898,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<location line="+68"/>
- <location filename="../rpcconsole.cpp" line="+1160"/>
+ <location filename="../rpcconsole.cpp" line="+1155"/>
<source>Select a peer to view detailed information.</source>
<translation type="unfinished"></translation>
</message>
@@ -2833,34 +2940,37 @@ If you are receiving this error you should request the merchant provide a BIP21
<message>
<location line="+23"/>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+23"/>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Addresses Processed</source>
+ <location line="+26"/>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+23"/>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
+ <location line="-23"/>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+26"/>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
@@ -3021,7 +3131,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../rpcconsole.cpp" line="-201"/>
+ <location filename="../rpcconsole.cpp" line="-202"/>
<source>In:</source>
<translation type="unfinished"></translation>
</message>
@@ -3066,12 +3176,12 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+41"/>
+ <location line="+42"/>
<source>Never</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../rpcconsole.cpp" line="-457"/>
+ <location filename="../rpcconsole.cpp" line="-458"/>
<source>Inbound: initiated by peer</source>
<extracomment>Explanatory text for an inbound peer connection.</extracomment>
<translation type="unfinished"></translation>
@@ -3177,7 +3287,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+26"/>
<source>&amp;Copy IP/Netmask</source>
<extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer&apos;s IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
<translation type="unfinished"></translation>
@@ -3193,17 +3303,37 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+77"/>
+ <location line="+78"/>
<source>Executing command without any wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-2"/>
+ <location line="+316"/>
+ <source>Ctrl+I</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Ctrl+T</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Ctrl+N</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Ctrl+P</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-321"/>
<source>Executing command using &quot;%1&quot; wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-145"/>
+ <location line="-146"/>
<source>Welcome to the %1 RPC console.
Use up and down arrows to navigate history, and %2 to clear screen.
Use %3 and %4 to increase or decrease the font size.
@@ -3215,7 +3345,7 @@ For more information on using this console, type %6.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+155"/>
+ <location line="+156"/>
<source>Executing…</source>
<extracomment>A console message indicating an entered command is currently being executed.</extracomment>
<translation type="unfinished"></translation>
@@ -3231,7 +3361,7 @@ For more information on using this console, type %6.
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../rpcconsole.h" line="-41"/>
+ <location filename="../rpcconsole.h" line="-42"/>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
@@ -3446,7 +3576,7 @@ For more information on using this console, type %6.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+41"/>
+ <location line="+38"/>
<source>(no label)</source>
<translation type="unfinished"></translation>
</message>
@@ -3467,10 +3597,43 @@ For more information on using this console, type %6.
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <location filename="../walletcontroller.cpp" line="+49"/>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+752"/>
+ <location filename="../sendcoinsdialog.cpp" line="+757"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -3657,7 +3820,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation>S&amp;end</translation>
</message>
<message>
- <location filename="../sendcoinsdialog.cpp" line="-653"/>
+ <location filename="../sendcoinsdialog.cpp" line="-658"/>
<source>Copy quantity</source>
<translation type="unfinished"></translation>
</message>
@@ -3692,7 +3855,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+76"/>
+ <location line="+74"/>
<source>%1 (%2 blocks)</source>
<translation type="unfinished"></translation>
</message>
@@ -3739,29 +3902,29 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+67"/>
+ <location line="+66"/>
<source>To review recipient list click &quot;Show Details…&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+44"/>
+ <location line="+60"/>
<source>Sign failed</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+5"/>
<source>External signer not found</source>
<extracomment>&quot;External signer&quot; means using devices such as hardware wallets.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+5"/>
<source>External signer failure</source>
<extracomment>&quot;External signer&quot; means using devices such as hardware wallets.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+58"/>
+ <location line="-34"/>
<source>Save Transaction Data</source>
<translation type="unfinished"></translation>
</message>
@@ -3777,17 +3940,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+176"/>
+ <location line="+266"/>
<source>External balance:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-303"/>
+ <location line="-315"/>
<source>or</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-19"/>
+ <location line="-18"/>
<source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
<translation type="unfinished"></translation>
</message>
@@ -3826,17 +3989,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+14"/>
+ <location line="+13"/>
<source>Total Amount</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+99"/>
<source>Confirm send coins</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+284"/>
+ <location line="+222"/>
<source>Watch-only balance:</source>
<translation type="unfinished"></translation>
</message>
@@ -3875,13 +4038,8 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location line="+3"/>
- <source>Payment request expired.</source>
- <translation type="unfinished"></translation>
- </message>
<message numerus="yes">
- <location line="+124"/>
+ <location line="+123"/>
<source>Estimated to begin confirmation within %n block(s).</source>
<translation>
<numerusform>Estimated to begin confirmation within %n block.</numerusform>
@@ -3917,14 +4075,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<context>
<name>SendCoinsEntry</name>
<message>
- <location filename="../forms/sendcoinsentry.ui" line="+155"/>
- <location line="+550"/>
- <location line="+533"/>
+ <location filename="../forms/sendcoinsentry.ui" line="+151"/>
<source>A&amp;mount:</source>
<translation>A&amp;mount:</translation>
</message>
<message>
- <location line="-1199"/>
+ <location line="-116"/>
<source>Pay &amp;To:</source>
<translation>Pay &amp;To:</translation>
</message>
@@ -3960,13 +4116,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</message>
<message>
<location line="+7"/>
- <location line="+562"/>
- <location line="+533"/>
<source>Remove this entry</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1035"/>
+ <location line="+60"/>
<source>The amount to send in the selected unit</source>
<translation type="unfinished"></translation>
</message>
@@ -3991,17 +4145,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+443"/>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+529"/>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="-1023"/>
+ <location line="-51"/>
<location line="+3"/>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished"></translation>
@@ -4011,23 +4155,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location line="+448"/>
- <location line="+529"/>
- <source>Pay To:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="-495"/>
- <location line="+533"/>
- <source>Memo:</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
<message>
- <location filename="../sendcoinsdialog.h" line="+131"/>
+ <location filename="../sendcoinsdialog.h" line="+144"/>
<source>Send</source>
<translation type="unfinished"></translation>
</message>
@@ -4274,42 +4406,43 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<context>
<name>TransactionDesc</name>
<message>
- <location filename="../transactiondesc.cpp" line="+40"/>
+ <location filename="../transactiondesc.cpp" line="+43"/>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+0"/>
- <source>in memory pool</source>
+ <location line="+7"/>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+0"/>
- <source>not in memory pool</source>
+ <location line="+5"/>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1"/>
+ <location line="+6"/>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+8"/>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+5"/>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+51"/>
+ <location line="+50"/>
<source>Status</source>
<translation type="unfinished"></translation>
</message>
@@ -4507,7 +4640,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<context>
<name>TransactionTableModel</name>
<message>
- <location filename="../transactiontablemodel.cpp" line="+260"/>
+ <location filename="../transactiontablemodel.cpp" line="+261"/>
<source>Date</source>
<translation type="unfinished">Date</translation>
</message>
@@ -4844,7 +4977,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
<context>
<name>WalletController</name>
<message>
- <location filename="../walletcontroller.cpp" line="-259"/>
+ <location filename="../walletcontroller.cpp" line="-344"/>
<source>Close wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -4884,19 +5017,19 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+154"/>
- <location line="+9"/>
+ <location line="+151"/>
<location line="+10"/>
+ <location line="+18"/>
<source>Error</source>
<translation type="unfinished">Error</translation>
</message>
<message>
- <location line="-19"/>
+ <location line="-28"/>
<source>Unable to decode PSBT from clipboard (invalid base64)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+6"/>
<source>Load Transaction Data</source>
<translation type="unfinished"></translation>
</message>
@@ -4911,7 +5044,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+18"/>
<source>Unable to decode PSBT</source>
<translation type="unfinished"></translation>
</message>
@@ -4919,12 +5052,12 @@ Go to File &gt; Open Wallet to load a wallet.
<context>
<name>WalletModel</name>
<message>
- <location filename="../walletmodel.cpp" line="+221"/>
+ <location filename="../walletmodel.cpp" line="+232"/>
<source>Send Coins</source>
<translation type="unfinished">Send Coins</translation>
</message>
<message>
- <location line="+260"/>
+ <location line="+263"/>
<location line="+52"/>
<location line="+15"/>
<location line="+5"/>
@@ -5001,7 +5134,7 @@ Go to File &gt; Open Wallet to load a wallet.
<context>
<name>WalletView</name>
<message>
- <location filename="../walletview.cpp" line="+52"/>
+ <location filename="../walletview.cpp" line="+51"/>
<source>&amp;Export</source>
<translation type="unfinished">&amp;Export</translation>
</message>
@@ -5011,7 +5144,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished">Export the data in the current tab to a file</translation>
</message>
<message>
- <location line="+164"/>
+ <location line="+162"/>
<source>Backup Wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -5060,12 +5193,12 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+7"/>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+18"/>
<source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
<translation type="unfinished"></translation>
</message>
@@ -5095,7 +5228,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+6"/>
<source>Error: Dumpfile format record is incorrect. Got &quot;%s&quot;, expected &quot;format&quot;.</source>
<translation type="unfinished"></translation>
</message>
@@ -5110,17 +5243,12 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+6"/>
<source>Error: Legacy wallets only support the &quot;legacy&quot;, &quot;p2sh-segwit&quot;, and &quot;bech32&quot; address types</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
+ <location line="+12"/>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished"></translation>
</message>
@@ -5130,7 +5258,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+6"/>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: &apos;%s&apos; (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation type="unfinished"></translation>
</message>
@@ -5160,7 +5288,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+10"/>
<source>Please check that your computer&apos;s date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation type="unfinished"></translation>
</message>
@@ -5176,6 +5304,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+2"/>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished"></translation>
</message>
@@ -5240,7 +5373,17 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+11"/>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+3"/>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
<source>Warning: Dumpfile wallet format &quot;%s&quot; does not match command line specified format &quot;%s&quot;.</source>
<translation type="unfinished"></translation>
</message>
@@ -5265,7 +5408,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+9"/>
<source>%s is set very high!</source>
<translation type="unfinished"></translation>
</message>
@@ -5300,12 +5443,37 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-58"/>
+ <location line="-79"/>
<source>The -txindex upgrade started by a previous version cannot be completed. Restart with the previous version or run a full -reindex.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-69"/>
+ <location line="-122"/>
+ <source>%s request to listen on port %u. This port is considered &quot;bad&quot; and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+8"/>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
<translation type="unfinished"></translation>
</message>
@@ -5315,7 +5483,73 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+118"/>
+ <location line="+9"/>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</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>
+ <message>
+ <location line="+9"/>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+21"/>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>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>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+59"/>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+24"/>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+10"/>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished"></translation>
</message>
@@ -5416,7 +5650,12 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
- <source>Error upgrading chainstate database</source>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: Could not delete watchonly transactions</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -5436,6 +5675,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Error: Got key that was not hex: %s</source>
<translation type="unfinished"></translation>
</message>
@@ -5461,11 +5705,46 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Error: Unable to write record to new wallet</source>
<translation type="unfinished"></translation>
</message>
@@ -5566,6 +5845,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Loading P2P addresses…</source>
<translation type="unfinished"></translation>
</message>
@@ -5606,11 +5890,6 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Not enough file descriptors available.</source>
<translation type="unfinished"></translation>
</message>
@@ -5621,11 +5900,6 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished"></translation>
</message>
@@ -5776,6 +6050,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
+ <source>Unable to allocate memory for -maxsigcachesize: &apos;%s&apos; MiB</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished"></translation>
</message>
@@ -5791,6 +6070,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Unable to generate initial keys</source>
<translation type="unfinished"></translation>
</message>
@@ -5816,6 +6100,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Unknown -blockfilterindex value %s.</source>
<translation type="unfinished"></translation>
</message>
@@ -5841,12 +6130,12 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+1"/>
- <source>Unsupported logging category %s=%s.</source>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
- <source>Upgrading UTXO database</source>
+ <source>Unsupported logging category %s=%s.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -5870,7 +6159,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="-496"/>
+ <location filename="../bitcoin.cpp" line="-519"/>
<source>Settings file could not be read</source>
<translation type="unfinished"></translation>
</message>
diff --git a/src/qt/locale/bitcoin_en.xlf b/src/qt/locale/bitcoin_en.xlf
index 30ee5e4de6..a25ccfca72 100644
--- a/src/qt/locale/bitcoin_en.xlf
+++ b/src/qt/locale/bitcoin_en.xlf
@@ -45,7 +45,7 @@
<trans-unit id="_msg11">
<source xml:space="preserve">&amp;Delete</source>
<context-group purpose="location"><context context-type="linenumber">101</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">../addressbookpage.cpp</context><context context-type="linenumber">122</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../addressbookpage.cpp</context><context context-type="linenumber">128</context></context-group>
</trans-unit>
</group>
</body></file>
@@ -53,62 +53,62 @@
<group restype="x-trolltech-linguist-context" resname="AddressBookPage">
<trans-unit id="_msg12">
<source xml:space="preserve">Choose the address to send coins to</source>
- <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
<trans-unit id="_msg13">
<source xml:space="preserve">Choose the address to receive coins with</source>
- <context-group purpose="location"><context context-type="linenumber">85</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">91</context></context-group>
</trans-unit>
<trans-unit id="_msg14">
<source xml:space="preserve">C&amp;hoose</source>
- <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
<trans-unit id="_msg15">
<source xml:space="preserve">Sending addresses</source>
- <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">102</context></context-group>
</trans-unit>
<trans-unit id="_msg16">
<source xml:space="preserve">Receiving addresses</source>
- <context-group purpose="location"><context context-type="linenumber">97</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">103</context></context-group>
</trans-unit>
<trans-unit id="_msg17">
<source xml:space="preserve">These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <context-group purpose="location"><context context-type="linenumber">104</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">110</context></context-group>
</trans-unit>
<trans-unit id="_msg18">
<source xml:space="preserve">These are your Bitcoin addresses for receiving payments. Use the &apos;Create new receiving address&apos; button in the receive tab to create new addresses.
Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
- <context-group purpose="location"><context context-type="linenumber">109</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">115</context></context-group>
</trans-unit>
<trans-unit id="_msg19">
<source xml:space="preserve">&amp;Copy Address</source>
- <context-group purpose="location"><context context-type="linenumber">117</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">123</context></context-group>
</trans-unit>
<trans-unit id="_msg20">
<source xml:space="preserve">Copy &amp;Label</source>
- <context-group purpose="location"><context context-type="linenumber">118</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">124</context></context-group>
</trans-unit>
<trans-unit id="_msg21">
<source xml:space="preserve">&amp;Edit</source>
- <context-group purpose="location"><context context-type="linenumber">119</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">125</context></context-group>
</trans-unit>
<trans-unit id="_msg22">
<source xml:space="preserve">Export Address List</source>
- <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">289</context></context-group>
</trans-unit>
<trans-unit id="_msg23">
<source xml:space="preserve">Comma separated file</source>
- <context-group purpose="location"><context context-type="linenumber">286</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
<note annotates="source" from="developer">Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</note>
</trans-unit>
<trans-unit id="_msg24">
<source xml:space="preserve">There was an error trying to save the address list to %1. Please try again.</source>
- <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
<note annotates="source" from="developer">An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</note>
</trans-unit>
<trans-unit id="_msg25">
<source xml:space="preserve">Exporting Failed</source>
- <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
</group>
</body></file>
@@ -267,568 +267,614 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<file original="../bitcoin.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="BitcoinApplication">
<trans-unit id="_msg58">
- <source xml:space="preserve">Runaway exception</source>
- <context-group purpose="location"><context context-type="linenumber">433</context></context-group>
+ <source xml:space="preserve">Settings file %1 might be corrupt or invalid.</source>
+ <context-group purpose="location"><context context-type="linenumber">288</context></context-group>
</trans-unit>
<trans-unit id="_msg59">
- <source xml:space="preserve">A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <context-group purpose="location"><context context-type="linenumber">434</context></context-group>
+ <source xml:space="preserve">Runaway exception</source>
+ <context-group purpose="location"><context context-type="linenumber">466</context></context-group>
</trans-unit>
<trans-unit id="_msg60">
- <source xml:space="preserve">Internal error</source>
- <context-group purpose="location"><context context-type="linenumber">443</context></context-group>
+ <source xml:space="preserve">A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <context-group purpose="location"><context context-type="linenumber">467</context></context-group>
</trans-unit>
<trans-unit id="_msg61">
+ <source xml:space="preserve">Internal error</source>
+ <context-group purpose="location"><context context-type="linenumber">476</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg62">
<source xml:space="preserve">An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <context-group purpose="location"><context context-type="linenumber">444</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">477</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg62">
+ <trans-unit id="_msg63">
<source xml:space="preserve">Do you want to reset settings to default values, or to abort without making changes?</source>
- <context-group purpose="location"><context context-type="linenumber">168</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">183</context></context-group>
<note annotates="source" from="developer">Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</note>
</trans-unit>
- <trans-unit id="_msg63">
+ <trans-unit id="_msg64">
<source xml:space="preserve">A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
- <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">207</context></context-group>
<note annotates="source" from="developer">Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</note>
</trans-unit>
- <trans-unit id="_msg64">
+ <trans-unit id="_msg65">
<source xml:space="preserve">Error: Specified data directory &quot;%1&quot; does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">565</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">600</context></context-group>
</trans-unit>
- <trans-unit id="_msg65">
+ <trans-unit id="_msg66">
<source xml:space="preserve">Error: Cannot parse configuration file: %1.</source>
- <context-group purpose="location"><context context-type="linenumber">571</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">606</context></context-group>
</trans-unit>
- <trans-unit id="_msg66">
+ <trans-unit id="_msg67">
<source xml:space="preserve">Error: %1</source>
- <context-group purpose="location"><context context-type="linenumber">586</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">621</context></context-group>
</trans-unit>
- <trans-unit id="_msg67">
+ <trans-unit id="_msg68">
<source xml:space="preserve">%1 didn&apos;t yet exit safely…</source>
- <context-group purpose="location"><context context-type="linenumber">657</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">695</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="bitcoin-core">
- <trans-unit id="_msg68">
+ <trans-unit id="_msg69">
<source xml:space="preserve">Settings file could not be read</source>
- <context-group purpose="location"><context context-type="linenumber">161</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">176</context></context-group>
</trans-unit>
- <trans-unit id="_msg69">
+ <trans-unit id="_msg70">
<source xml:space="preserve">Settings file could not be written</source>
- <context-group purpose="location"><context context-type="linenumber">184</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../bitcoingui.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="BitcoinGUI">
- <trans-unit id="_msg70">
- <source xml:space="preserve">&amp;Overview</source>
- <context-group purpose="location"><context context-type="linenumber">250</context></context-group>
- </trans-unit>
<trans-unit id="_msg71">
- <source xml:space="preserve">Show general overview of wallet</source>
- <context-group purpose="location"><context context-type="linenumber">251</context></context-group>
+ <source xml:space="preserve">&amp;Overview</source>
+ <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
</trans-unit>
<trans-unit id="_msg72">
- <source xml:space="preserve">&amp;Transactions</source>
- <context-group purpose="location"><context context-type="linenumber">271</context></context-group>
+ <source xml:space="preserve">Show general overview of wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
</trans-unit>
<trans-unit id="_msg73">
- <source xml:space="preserve">Browse transaction history</source>
- <context-group purpose="location"><context context-type="linenumber">272</context></context-group>
+ <source xml:space="preserve">&amp;Transactions</source>
+ <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
<trans-unit id="_msg74">
- <source xml:space="preserve">E&amp;xit</source>
- <context-group purpose="location"><context context-type="linenumber">291</context></context-group>
+ <source xml:space="preserve">Browse transaction history</source>
+ <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
</trans-unit>
<trans-unit id="_msg75">
- <source xml:space="preserve">Quit application</source>
- <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
+ <source xml:space="preserve">E&amp;xit</source>
+ <context-group purpose="location"><context context-type="linenumber">294</context></context-group>
</trans-unit>
<trans-unit id="_msg76">
- <source xml:space="preserve">&amp;About %1</source>
+ <source xml:space="preserve">Quit application</source>
<context-group purpose="location"><context context-type="linenumber">295</context></context-group>
</trans-unit>
<trans-unit id="_msg77">
- <source xml:space="preserve">Show information about %1</source>
- <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
+ <source xml:space="preserve">&amp;About %1</source>
+ <context-group purpose="location"><context context-type="linenumber">298</context></context-group>
</trans-unit>
<trans-unit id="_msg78">
- <source xml:space="preserve">About &amp;Qt</source>
+ <source xml:space="preserve">Show information about %1</source>
<context-group purpose="location"><context context-type="linenumber">299</context></context-group>
</trans-unit>
<trans-unit id="_msg79">
- <source xml:space="preserve">Show information about Qt</source>
- <context-group purpose="location"><context context-type="linenumber">300</context></context-group>
+ <source xml:space="preserve">About &amp;Qt</source>
+ <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
</trans-unit>
<trans-unit id="_msg80">
- <source xml:space="preserve">Modify configuration options for %1</source>
+ <source xml:space="preserve">Show information about Qt</source>
<context-group purpose="location"><context context-type="linenumber">303</context></context-group>
</trans-unit>
<trans-unit id="_msg81">
- <source xml:space="preserve">Create a new wallet</source>
- <context-group purpose="location"><context context-type="linenumber">347</context></context-group>
+ <source xml:space="preserve">Modify configuration options for %1</source>
+ <context-group purpose="location"><context context-type="linenumber">306</context></context-group>
</trans-unit>
<trans-unit id="_msg82">
- <source xml:space="preserve">&amp;Minimize</source>
- <context-group purpose="location"><context context-type="linenumber">474</context></context-group>
+ <source xml:space="preserve">Create a new wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
</trans-unit>
<trans-unit id="_msg83">
- <source xml:space="preserve">Wallet:</source>
- <context-group purpose="location"><context context-type="linenumber">553</context></context-group>
+ <source xml:space="preserve">&amp;Minimize</source>
+ <context-group purpose="location"><context context-type="linenumber">510</context></context-group>
</trans-unit>
<trans-unit id="_msg84">
- <source xml:space="preserve">Network activity disabled.</source>
- <context-group purpose="location"><context context-type="linenumber">945</context></context-group>
- <note annotates="source" from="developer">A substring of the tooltip.</note>
+ <source xml:space="preserve">Wallet:</source>
+ <context-group purpose="location"><context context-type="linenumber">589</context></context-group>
</trans-unit>
<trans-unit id="_msg85">
- <source xml:space="preserve">Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1367</context></context-group>
+ <source xml:space="preserve">Network activity disabled.</source>
+ <context-group purpose="location"><context context-type="linenumber">982</context></context-group>
+ <note annotates="source" from="developer">A substring of the tooltip.</note>
</trans-unit>
<trans-unit id="_msg86">
- <source xml:space="preserve">Send coins to a Bitcoin address</source>
- <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
+ <source xml:space="preserve">Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <context-group purpose="location"><context context-type="linenumber">1421</context></context-group>
</trans-unit>
<trans-unit id="_msg87">
- <source xml:space="preserve">Backup wallet to another location</source>
- <context-group purpose="location"><context context-type="linenumber">311</context></context-group>
+ <source xml:space="preserve">Send coins to a Bitcoin address</source>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
<trans-unit id="_msg88">
- <source xml:space="preserve">Change the passphrase used for wallet encryption</source>
- <context-group purpose="location"><context context-type="linenumber">313</context></context-group>
+ <source xml:space="preserve">Backup wallet to another location</source>
+ <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
</trans-unit>
<trans-unit id="_msg89">
- <source xml:space="preserve">&amp;Send</source>
- <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
+ <source xml:space="preserve">Change the passphrase used for wallet encryption</source>
+ <context-group purpose="location"><context context-type="linenumber">316</context></context-group>
</trans-unit>
<trans-unit id="_msg90">
- <source xml:space="preserve">&amp;Receive</source>
- <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
+ <source xml:space="preserve">&amp;Send</source>
+ <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
<trans-unit id="_msg91">
- <source xml:space="preserve">&amp;Options…</source>
- <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
+ <source xml:space="preserve">&amp;Receive</source>
+ <context-group purpose="location"><context context-type="linenumber">267</context></context-group>
</trans-unit>
<trans-unit id="_msg92">
- <source xml:space="preserve">&amp;Encrypt Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">307</context></context-group>
+ <source xml:space="preserve">&amp;Options…</source>
+ <context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
<trans-unit id="_msg93">
- <source xml:space="preserve">Encrypt the private keys that belong to your wallet</source>
- <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
+ <source xml:space="preserve">&amp;Encrypt Wallet…</source>
+ <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
</trans-unit>
<trans-unit id="_msg94">
- <source xml:space="preserve">&amp;Backup Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
+ <source xml:space="preserve">Encrypt the private keys that belong to your wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">311</context></context-group>
</trans-unit>
<trans-unit id="_msg95">
- <source xml:space="preserve">&amp;Change Passphrase…</source>
- <context-group purpose="location"><context context-type="linenumber">312</context></context-group>
+ <source xml:space="preserve">&amp;Backup Wallet…</source>
+ <context-group purpose="location"><context context-type="linenumber">313</context></context-group>
</trans-unit>
<trans-unit id="_msg96">
- <source xml:space="preserve">Sign &amp;message…</source>
- <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
+ <source xml:space="preserve">&amp;Change Passphrase…</source>
+ <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
</trans-unit>
<trans-unit id="_msg97">
- <source xml:space="preserve">Sign messages with your Bitcoin addresses to prove you own them</source>
- <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
+ <source xml:space="preserve">Sign &amp;message…</source>
+ <context-group purpose="location"><context context-type="linenumber">317</context></context-group>
</trans-unit>
<trans-unit id="_msg98">
- <source xml:space="preserve">&amp;Verify message…</source>
- <context-group purpose="location"><context context-type="linenumber">316</context></context-group>
+ <source xml:space="preserve">Sign messages with your Bitcoin addresses to prove you own them</source>
+ <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
</trans-unit>
<trans-unit id="_msg99">
- <source xml:space="preserve">Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <context-group purpose="location"><context context-type="linenumber">317</context></context-group>
+ <source xml:space="preserve">&amp;Verify message…</source>
+ <context-group purpose="location"><context context-type="linenumber">319</context></context-group>
</trans-unit>
<trans-unit id="_msg100">
- <source xml:space="preserve">&amp;Load PSBT from file…</source>
- <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
+ <source xml:space="preserve">Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
</trans-unit>
<trans-unit id="_msg101">
- <source xml:space="preserve">Open &amp;URI…</source>
- <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
+ <source xml:space="preserve">&amp;Load PSBT from file…</source>
+ <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
<trans-unit id="_msg102">
- <source xml:space="preserve">Close Wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
+ <source xml:space="preserve">Open &amp;URI…</source>
+ <context-group purpose="location"><context context-type="linenumber">337</context></context-group>
</trans-unit>
<trans-unit id="_msg103">
- <source xml:space="preserve">Create Wallet…</source>
+ <source xml:space="preserve">Close Wallet…</source>
<context-group purpose="location"><context context-type="linenumber">345</context></context-group>
</trans-unit>
<trans-unit id="_msg104">
- <source xml:space="preserve">Close All Wallets…</source>
- <context-group purpose="location"><context context-type="linenumber">349</context></context-group>
+ <source xml:space="preserve">Create Wallet…</source>
+ <context-group purpose="location"><context context-type="linenumber">348</context></context-group>
</trans-unit>
<trans-unit id="_msg105">
- <source xml:space="preserve">&amp;File</source>
- <context-group purpose="location"><context context-type="linenumber">443</context></context-group>
+ <source xml:space="preserve">Close All Wallets…</source>
+ <context-group purpose="location"><context context-type="linenumber">358</context></context-group>
</trans-unit>
<trans-unit id="_msg106">
- <source xml:space="preserve">&amp;Settings</source>
- <context-group purpose="location"><context context-type="linenumber">461</context></context-group>
+ <source xml:space="preserve">&amp;File</source>
+ <context-group purpose="location"><context context-type="linenumber">477</context></context-group>
</trans-unit>
<trans-unit id="_msg107">
- <source xml:space="preserve">&amp;Help</source>
- <context-group purpose="location"><context context-type="linenumber">522</context></context-group>
+ <source xml:space="preserve">&amp;Settings</source>
+ <context-group purpose="location"><context context-type="linenumber">497</context></context-group>
</trans-unit>
<trans-unit id="_msg108">
- <source xml:space="preserve">Tabs toolbar</source>
- <context-group purpose="location"><context context-type="linenumber">533</context></context-group>
+ <source xml:space="preserve">&amp;Help</source>
+ <context-group purpose="location"><context context-type="linenumber">558</context></context-group>
</trans-unit>
<trans-unit id="_msg109">
- <source xml:space="preserve">Syncing Headers (%1%)…</source>
- <context-group purpose="location"><context context-type="linenumber">989</context></context-group>
+ <source xml:space="preserve">Tabs toolbar</source>
+ <context-group purpose="location"><context context-type="linenumber">569</context></context-group>
</trans-unit>
<trans-unit id="_msg110">
- <source xml:space="preserve">Synchronizing with network…</source>
- <context-group purpose="location"><context context-type="linenumber">1036</context></context-group>
+ <source xml:space="preserve">Syncing Headers (%1%)…</source>
+ <context-group purpose="location"><context context-type="linenumber">1026</context></context-group>
</trans-unit>
<trans-unit id="_msg111">
- <source xml:space="preserve">Indexing blocks on disk…</source>
- <context-group purpose="location"><context context-type="linenumber">1041</context></context-group>
+ <source xml:space="preserve">Synchronizing with network…</source>
+ <context-group purpose="location"><context context-type="linenumber">1084</context></context-group>
</trans-unit>
<trans-unit id="_msg112">
- <source xml:space="preserve">Processing blocks on disk…</source>
- <context-group purpose="location"><context context-type="linenumber">1043</context></context-group>
+ <source xml:space="preserve">Indexing blocks on disk…</source>
+ <context-group purpose="location"><context context-type="linenumber">1089</context></context-group>
</trans-unit>
<trans-unit id="_msg113">
- <source xml:space="preserve">Reindexing blocks on disk…</source>
- <context-group purpose="location"><context context-type="linenumber">1047</context></context-group>
+ <source xml:space="preserve">Processing blocks on disk…</source>
+ <context-group purpose="location"><context context-type="linenumber">1091</context></context-group>
</trans-unit>
<trans-unit id="_msg114">
- <source xml:space="preserve">Connecting to peers…</source>
- <context-group purpose="location"><context context-type="linenumber">1053</context></context-group>
+ <source xml:space="preserve">Reindexing blocks on disk…</source>
+ <context-group purpose="location"><context context-type="linenumber">1095</context></context-group>
</trans-unit>
<trans-unit id="_msg115">
- <source xml:space="preserve">Request payments (generates QR codes and bitcoin: URIs)</source>
- <context-group purpose="location"><context context-type="linenumber">265</context></context-group>
+ <source xml:space="preserve">Connecting to peers…</source>
+ <context-group purpose="location"><context context-type="linenumber">1101</context></context-group>
</trans-unit>
<trans-unit id="_msg116">
- <source xml:space="preserve">Show the list of used sending addresses and labels</source>
- <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
+ <source xml:space="preserve">Request payments (generates QR codes and bitcoin: URIs)</source>
+ <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
</trans-unit>
<trans-unit id="_msg117">
- <source xml:space="preserve">Show the list of used receiving addresses and labels</source>
- <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
+ <source xml:space="preserve">Show the list of used sending addresses and labels</source>
+ <context-group purpose="location"><context context-type="linenumber">333</context></context-group>
</trans-unit>
<trans-unit id="_msg118">
+ <source xml:space="preserve">Show the list of used receiving addresses and labels</source>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg119">
<source xml:space="preserve">&amp;Command-line options</source>
- <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">361</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">1062</context></context-group>
- <trans-unit id="_msg119[0]">
+ <context-group purpose="location"><context context-type="linenumber">1110</context></context-group>
+ <trans-unit id="_msg120[0]">
<source xml:space="preserve">Processed %n block(s) of transaction history.</source>
</trans-unit>
- <trans-unit id="_msg119[1]">
+ <trans-unit id="_msg120[1]">
<source xml:space="preserve">Processed %n block(s) of transaction history.</source>
</trans-unit>
</group>
- <trans-unit id="_msg120">
- <source xml:space="preserve">%1 behind</source>
- <context-group purpose="location"><context context-type="linenumber">1085</context></context-group>
- </trans-unit>
<trans-unit id="_msg121">
- <source xml:space="preserve">Catching up…</source>
- <context-group purpose="location"><context context-type="linenumber">1090</context></context-group>
+ <source xml:space="preserve">%1 behind</source>
+ <context-group purpose="location"><context context-type="linenumber">1133</context></context-group>
</trans-unit>
<trans-unit id="_msg122">
- <source xml:space="preserve">Last received block was generated %1 ago.</source>
- <context-group purpose="location"><context context-type="linenumber">1109</context></context-group>
+ <source xml:space="preserve">Catching up…</source>
+ <context-group purpose="location"><context context-type="linenumber">1138</context></context-group>
</trans-unit>
<trans-unit id="_msg123">
- <source xml:space="preserve">Transactions after this will not yet be visible.</source>
- <context-group purpose="location"><context context-type="linenumber">1111</context></context-group>
+ <source xml:space="preserve">Last received block was generated %1 ago.</source>
+ <context-group purpose="location"><context context-type="linenumber">1157</context></context-group>
</trans-unit>
<trans-unit id="_msg124">
- <source xml:space="preserve">Error</source>
- <context-group purpose="location"><context context-type="linenumber">1136</context></context-group>
+ <source xml:space="preserve">Transactions after this will not yet be visible.</source>
+ <context-group purpose="location"><context context-type="linenumber">1159</context></context-group>
</trans-unit>
<trans-unit id="_msg125">
- <source xml:space="preserve">Warning</source>
- <context-group purpose="location"><context context-type="linenumber">1140</context></context-group>
+ <source xml:space="preserve">Error</source>
+ <context-group purpose="location"><context context-type="linenumber">1184</context></context-group>
</trans-unit>
<trans-unit id="_msg126">
- <source xml:space="preserve">Information</source>
- <context-group purpose="location"><context context-type="linenumber">1144</context></context-group>
+ <source xml:space="preserve">Warning</source>
+ <context-group purpose="location"><context context-type="linenumber">1188</context></context-group>
</trans-unit>
<trans-unit id="_msg127">
- <source xml:space="preserve">Up to date</source>
- <context-group purpose="location"><context context-type="linenumber">1066</context></context-group>
+ <source xml:space="preserve">Information</source>
+ <context-group purpose="location"><context context-type="linenumber">1192</context></context-group>
</trans-unit>
<trans-unit id="_msg128">
- <source xml:space="preserve">Load Partially Signed Bitcoin Transaction</source>
- <context-group purpose="location"><context context-type="linenumber">319</context></context-group>
+ <source xml:space="preserve">Up to date</source>
+ <context-group purpose="location"><context context-type="linenumber">1114</context></context-group>
</trans-unit>
<trans-unit id="_msg129">
- <source xml:space="preserve">Load PSBT from &amp;clipboard…</source>
- <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
+ <source xml:space="preserve">Ctrl+Q</source>
+ <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
</trans-unit>
<trans-unit id="_msg130">
- <source xml:space="preserve">Load Partially Signed Bitcoin Transaction from clipboard</source>
- <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
+ <source xml:space="preserve">Load Partially Signed Bitcoin Transaction</source>
+ <context-group purpose="location"><context context-type="linenumber">322</context></context-group>
</trans-unit>
<trans-unit id="_msg131">
- <source xml:space="preserve">Node window</source>
+ <source xml:space="preserve">Load PSBT from &amp;clipboard…</source>
<context-group purpose="location"><context context-type="linenumber">323</context></context-group>
</trans-unit>
<trans-unit id="_msg132">
- <source xml:space="preserve">Open node debugging and diagnostic console</source>
+ <source xml:space="preserve">Load Partially Signed Bitcoin Transaction from clipboard</source>
<context-group purpose="location"><context context-type="linenumber">324</context></context-group>
</trans-unit>
<trans-unit id="_msg133">
- <source xml:space="preserve">&amp;Sending addresses</source>
- <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
+ <source xml:space="preserve">Node window</source>
+ <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
<trans-unit id="_msg134">
- <source xml:space="preserve">&amp;Receiving addresses</source>
- <context-group purpose="location"><context context-type="linenumber">331</context></context-group>
+ <source xml:space="preserve">Open node debugging and diagnostic console</source>
+ <context-group purpose="location"><context context-type="linenumber">327</context></context-group>
</trans-unit>
<trans-unit id="_msg135">
- <source xml:space="preserve">Open a bitcoin: URI</source>
- <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
+ <source xml:space="preserve">&amp;Sending addresses</source>
+ <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
</trans-unit>
<trans-unit id="_msg136">
- <source xml:space="preserve">Open Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">337</context></context-group>
+ <source xml:space="preserve">&amp;Receiving addresses</source>
+ <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
<trans-unit id="_msg137">
- <source xml:space="preserve">Open a wallet</source>
- <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
+ <source xml:space="preserve">Open a bitcoin: URI</source>
+ <context-group purpose="location"><context context-type="linenumber">338</context></context-group>
</trans-unit>
<trans-unit id="_msg138">
- <source xml:space="preserve">Close wallet</source>
- <context-group purpose="location"><context context-type="linenumber">343</context></context-group>
+ <source xml:space="preserve">Open Wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">340</context></context-group>
</trans-unit>
<trans-unit id="_msg139">
- <source xml:space="preserve">Close all wallets</source>
- <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
+ <source xml:space="preserve">Open a wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
</trans-unit>
<trans-unit id="_msg140">
- <source xml:space="preserve">Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <context-group purpose="location"><context context-type="linenumber">354</context></context-group>
+ <source xml:space="preserve">Close wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">346</context></context-group>
</trans-unit>
<trans-unit id="_msg141">
- <source xml:space="preserve">&amp;Mask values</source>
- <context-group purpose="location"><context context-type="linenumber">356</context></context-group>
+ <source xml:space="preserve">Restore Wallet…</source>
+ <context-group purpose="location"><context context-type="linenumber">353</context></context-group>
+ <note annotates="source" from="developer">Name of the menu item that restores wallet from a backup file.</note>
</trans-unit>
<trans-unit id="_msg142">
- <source xml:space="preserve">Mask the values in the Overview tab</source>
- <context-group purpose="location"><context context-type="linenumber">358</context></context-group>
+ <source xml:space="preserve">Restore a wallet from a backup file</source>
+ <context-group purpose="location"><context context-type="linenumber">356</context></context-group>
+ <note annotates="source" from="developer">Status tip for Restore Wallet menu item</note>
</trans-unit>
<trans-unit id="_msg143">
- <source xml:space="preserve">default wallet</source>
- <context-group purpose="location"><context context-type="linenumber">389</context></context-group>
+ <source xml:space="preserve">Close all wallets</source>
+ <context-group purpose="location"><context context-type="linenumber">359</context></context-group>
</trans-unit>
<trans-unit id="_msg144">
- <source xml:space="preserve">No wallets available</source>
- <context-group purpose="location"><context context-type="linenumber">409</context></context-group>
+ <source xml:space="preserve">Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <context-group purpose="location"><context context-type="linenumber">363</context></context-group>
</trans-unit>
<trans-unit id="_msg145">
- <source xml:space="preserve">&amp;Window</source>
- <context-group purpose="location"><context context-type="linenumber">472</context></context-group>
+ <source xml:space="preserve">&amp;Mask values</source>
+ <context-group purpose="location"><context context-type="linenumber">365</context></context-group>
</trans-unit>
<trans-unit id="_msg146">
- <source xml:space="preserve">Zoom</source>
- <context-group purpose="location"><context context-type="linenumber">484</context></context-group>
+ <source xml:space="preserve">Mask the values in the Overview tab</source>
+ <context-group purpose="location"><context context-type="linenumber">367</context></context-group>
</trans-unit>
<trans-unit id="_msg147">
- <source xml:space="preserve">Main Window</source>
- <context-group purpose="location"><context context-type="linenumber">502</context></context-group>
+ <source xml:space="preserve">default wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">398</context></context-group>
</trans-unit>
<trans-unit id="_msg148">
- <source xml:space="preserve">%1 client</source>
- <context-group purpose="location"><context context-type="linenumber">759</context></context-group>
+ <source xml:space="preserve">No wallets available</source>
+ <context-group purpose="location"><context context-type="linenumber">418</context></context-group>
</trans-unit>
<trans-unit id="_msg149">
- <source xml:space="preserve">&amp;Hide</source>
- <context-group purpose="location"><context context-type="linenumber">824</context></context-group>
+ <source xml:space="preserve">Wallet Data</source>
+ <context-group purpose="location"><context context-type="linenumber">424</context></context-group>
+ <note annotates="source" from="developer">Name of the wallet data file format.</note>
</trans-unit>
<trans-unit id="_msg150">
+ <source xml:space="preserve">Load Wallet Backup</source>
+ <context-group purpose="location"><context context-type="linenumber">427</context></context-group>
+ <note annotates="source" from="developer">The title for Restore Wallet File Windows</note>
+ </trans-unit>
+ <trans-unit id="_msg151">
+ <source xml:space="preserve">Restore Wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">435</context></context-group>
+ <note annotates="source" from="developer">Title of pop-up window shown when the user is attempting to restore a wallet.</note>
+ </trans-unit>
+ <trans-unit id="_msg152">
+ <source xml:space="preserve">Wallet Name</source>
+ <context-group purpose="location"><context context-type="linenumber">437</context></context-group>
+ <note annotates="source" from="developer">Label of the input field where the name of the wallet is entered.</note>
+ </trans-unit>
+ <trans-unit id="_msg153">
+ <source xml:space="preserve">&amp;Window</source>
+ <context-group purpose="location"><context context-type="linenumber">508</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg154">
+ <source xml:space="preserve">Ctrl+M</source>
+ <context-group purpose="location"><context context-type="linenumber">511</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg155">
+ <source xml:space="preserve">Zoom</source>
+ <context-group purpose="location"><context context-type="linenumber">520</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg156">
+ <source xml:space="preserve">Main Window</source>
+ <context-group purpose="location"><context context-type="linenumber">538</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg157">
+ <source xml:space="preserve">%1 client</source>
+ <context-group purpose="location"><context context-type="linenumber">796</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg158">
+ <source xml:space="preserve">&amp;Hide</source>
+ <context-group purpose="location"><context context-type="linenumber">861</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg159">
<source xml:space="preserve">S&amp;how</source>
- <context-group purpose="location"><context context-type="linenumber">825</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">862</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">942</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">979</context></context-group>
<note annotates="source" from="developer">A substring of the tooltip.</note>
- <trans-unit id="_msg151[0]">
+ <trans-unit id="_msg160[0]">
<source xml:space="preserve">%n active connection(s) to Bitcoin network.</source>
</trans-unit>
- <trans-unit id="_msg151[1]">
+ <trans-unit id="_msg160[1]">
<source xml:space="preserve">%n active connection(s) to Bitcoin network.</source>
</trans-unit>
</group>
- <trans-unit id="_msg152">
+ <trans-unit id="_msg161">
<source xml:space="preserve">Click for more actions.</source>
- <context-group purpose="location"><context context-type="linenumber">952</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">989</context></context-group>
<note annotates="source" from="developer">A substring of the tooltip. &quot;More actions&quot; are available via the context menu.</note>
</trans-unit>
- <trans-unit id="_msg153">
+ <trans-unit id="_msg162">
<source xml:space="preserve">Show Peers tab</source>
- <context-group purpose="location"><context context-type="linenumber">969</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1006</context></context-group>
<note annotates="source" from="developer">A context menu item. The &quot;Peers tab&quot; is an element of the &quot;Node window&quot;.</note>
</trans-unit>
- <trans-unit id="_msg154">
+ <trans-unit id="_msg163">
<source xml:space="preserve">Disable network activity</source>
- <context-group purpose="location"><context context-type="linenumber">977</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1014</context></context-group>
<note annotates="source" from="developer">A context menu item.</note>
</trans-unit>
- <trans-unit id="_msg155">
+ <trans-unit id="_msg164">
<source xml:space="preserve">Enable network activity</source>
- <context-group purpose="location"><context context-type="linenumber">979</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1016</context></context-group>
<note annotates="source" from="developer">A context menu item. The network activity was disabled previously.</note>
</trans-unit>
- <trans-unit id="_msg156">
+ <trans-unit id="_msg165">
+ <source xml:space="preserve">Pre-syncing Headers (%1%)…</source>
+ <context-group purpose="location"><context context-type="linenumber">1033</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg166">
<source xml:space="preserve">Error: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1137</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1185</context></context-group>
</trans-unit>
- <trans-unit id="_msg157">
+ <trans-unit id="_msg167">
<source xml:space="preserve">Warning: %1</source>
- <context-group purpose="location"><context context-type="linenumber">1141</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1189</context></context-group>
</trans-unit>
- <trans-unit id="_msg158">
+ <trans-unit id="_msg168">
<source xml:space="preserve">Date: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1249</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1297</context></context-group>
</trans-unit>
- <trans-unit id="_msg159">
+ <trans-unit id="_msg169">
<source xml:space="preserve">Amount: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1250</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1298</context></context-group>
</trans-unit>
- <trans-unit id="_msg160">
+ <trans-unit id="_msg170">
<source xml:space="preserve">Wallet: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1252</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1300</context></context-group>
</trans-unit>
- <trans-unit id="_msg161">
+ <trans-unit id="_msg171">
<source xml:space="preserve">Type: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1254</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1302</context></context-group>
</trans-unit>
- <trans-unit id="_msg162">
+ <trans-unit id="_msg172">
<source xml:space="preserve">Label: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1256</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1304</context></context-group>
</trans-unit>
- <trans-unit id="_msg163">
+ <trans-unit id="_msg173">
<source xml:space="preserve">Address: %1
</source>
- <context-group purpose="location"><context context-type="linenumber">1258</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1306</context></context-group>
</trans-unit>
- <trans-unit id="_msg164">
+ <trans-unit id="_msg174">
<source xml:space="preserve">Sent transaction</source>
- <context-group purpose="location"><context context-type="linenumber">1259</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1307</context></context-group>
</trans-unit>
- <trans-unit id="_msg165">
+ <trans-unit id="_msg175">
<source xml:space="preserve">Incoming transaction</source>
- <context-group purpose="location"><context context-type="linenumber">1259</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1307</context></context-group>
</trans-unit>
- <trans-unit id="_msg166">
+ <trans-unit id="_msg176">
<source xml:space="preserve">HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1359</context></context-group>
</trans-unit>
- <trans-unit id="_msg167">
+ <trans-unit id="_msg177">
<source xml:space="preserve">HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1359</context></context-group>
</trans-unit>
- <trans-unit id="_msg168">
+ <trans-unit id="_msg178">
<source xml:space="preserve">Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1359</context></context-group>
</trans-unit>
- <trans-unit id="_msg169">
+ <trans-unit id="_msg179">
<source xml:space="preserve">Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1328</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1382</context></context-group>
</trans-unit>
- <trans-unit id="_msg170">
+ <trans-unit id="_msg180">
<source xml:space="preserve">Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <context-group purpose="location"><context context-type="linenumber">1336</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1390</context></context-group>
</trans-unit>
- <trans-unit id="_msg171">
+ <trans-unit id="_msg181">
<source xml:space="preserve">Original message:</source>
- <context-group purpose="location"><context context-type="linenumber">1455</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1509</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="UnitDisplayStatusBarControl">
- <trans-unit id="_msg172">
+ <trans-unit id="_msg182">
<source xml:space="preserve">Unit to show amounts in. Click to select another unit.</source>
- <context-group purpose="location"><context context-type="linenumber">1496</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1550</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/coincontroldialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CoinControlDialog">
- <trans-unit id="_msg173">
+ <trans-unit id="_msg183">
<source xml:space="preserve">Coin Selection</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg174">
+ <trans-unit id="_msg184">
<source xml:space="preserve">Quantity:</source>
<context-group purpose="location"><context context-type="linenumber">48</context></context-group>
</trans-unit>
- <trans-unit id="_msg175">
+ <trans-unit id="_msg185">
<source xml:space="preserve">Bytes:</source>
<context-group purpose="location"><context context-type="linenumber">77</context></context-group>
</trans-unit>
- <trans-unit id="_msg176">
+ <trans-unit id="_msg186">
<source xml:space="preserve">Amount:</source>
<context-group purpose="location"><context context-type="linenumber">122</context></context-group>
</trans-unit>
- <trans-unit id="_msg177">
+ <trans-unit id="_msg187">
<source xml:space="preserve">Fee:</source>
<context-group purpose="location"><context context-type="linenumber">202</context></context-group>
</trans-unit>
- <trans-unit id="_msg178">
+ <trans-unit id="_msg188">
<source xml:space="preserve">Dust:</source>
<context-group purpose="location"><context context-type="linenumber">154</context></context-group>
</trans-unit>
- <trans-unit id="_msg179">
+ <trans-unit id="_msg189">
<source xml:space="preserve">After Fee:</source>
<context-group purpose="location"><context context-type="linenumber">247</context></context-group>
</trans-unit>
- <trans-unit id="_msg180">
+ <trans-unit id="_msg190">
<source xml:space="preserve">Change:</source>
<context-group purpose="location"><context context-type="linenumber">279</context></context-group>
</trans-unit>
- <trans-unit id="_msg181">
+ <trans-unit id="_msg191">
<source xml:space="preserve">(un)select all</source>
<context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg182">
+ <trans-unit id="_msg192">
<source xml:space="preserve">Tree mode</source>
<context-group purpose="location"><context context-type="linenumber">351</context></context-group>
</trans-unit>
- <trans-unit id="_msg183">
+ <trans-unit id="_msg193">
<source xml:space="preserve">List mode</source>
<context-group purpose="location"><context context-type="linenumber">364</context></context-group>
</trans-unit>
- <trans-unit id="_msg184">
+ <trans-unit id="_msg194">
<source xml:space="preserve">Amount</source>
<context-group purpose="location"><context context-type="linenumber">420</context></context-group>
</trans-unit>
- <trans-unit id="_msg185">
+ <trans-unit id="_msg195">
<source xml:space="preserve">Received with label</source>
<context-group purpose="location"><context context-type="linenumber">425</context></context-group>
</trans-unit>
- <trans-unit id="_msg186">
+ <trans-unit id="_msg196">
<source xml:space="preserve">Received with address</source>
<context-group purpose="location"><context context-type="linenumber">430</context></context-group>
</trans-unit>
- <trans-unit id="_msg187">
+ <trans-unit id="_msg197">
<source xml:space="preserve">Date</source>
<context-group purpose="location"><context context-type="linenumber">435</context></context-group>
</trans-unit>
- <trans-unit id="_msg188">
+ <trans-unit id="_msg198">
<source xml:space="preserve">Confirmations</source>
<context-group purpose="location"><context context-type="linenumber">440</context></context-group>
</trans-unit>
- <trans-unit id="_msg189">
+ <trans-unit id="_msg199">
<source xml:space="preserve">Confirmed</source>
<context-group purpose="location"><context context-type="linenumber">443</context></context-group>
</trans-unit>
@@ -836,232 +882,263 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../coincontroldialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CoinControlDialog">
- <trans-unit id="_msg190">
+ <trans-unit id="_msg200">
<source xml:space="preserve">Copy amount</source>
<context-group purpose="location"><context context-type="linenumber">69</context></context-group>
</trans-unit>
- <trans-unit id="_msg191">
+ <trans-unit id="_msg201">
<source xml:space="preserve">&amp;Copy address</source>
<context-group purpose="location"><context context-type="linenumber">58</context></context-group>
</trans-unit>
- <trans-unit id="_msg192">
+ <trans-unit id="_msg202">
<source xml:space="preserve">Copy &amp;label</source>
<context-group purpose="location"><context context-type="linenumber">59</context></context-group>
</trans-unit>
- <trans-unit id="_msg193">
+ <trans-unit id="_msg203">
<source xml:space="preserve">Copy &amp;amount</source>
<context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
- <trans-unit id="_msg194">
+ <trans-unit id="_msg204">
<source xml:space="preserve">Copy transaction &amp;ID and output index</source>
<context-group purpose="location"><context context-type="linenumber">61</context></context-group>
</trans-unit>
- <trans-unit id="_msg195">
+ <trans-unit id="_msg205">
<source xml:space="preserve">L&amp;ock unspent</source>
<context-group purpose="location"><context context-type="linenumber">63</context></context-group>
</trans-unit>
- <trans-unit id="_msg196">
+ <trans-unit id="_msg206">
<source xml:space="preserve">&amp;Unlock unspent</source>
<context-group purpose="location"><context context-type="linenumber">64</context></context-group>
</trans-unit>
- <trans-unit id="_msg197">
+ <trans-unit id="_msg207">
<source xml:space="preserve">Copy quantity</source>
<context-group purpose="location"><context context-type="linenumber">68</context></context-group>
</trans-unit>
- <trans-unit id="_msg198">
+ <trans-unit id="_msg208">
<source xml:space="preserve">Copy fee</source>
<context-group purpose="location"><context context-type="linenumber">70</context></context-group>
</trans-unit>
- <trans-unit id="_msg199">
+ <trans-unit id="_msg209">
<source xml:space="preserve">Copy after fee</source>
<context-group purpose="location"><context context-type="linenumber">71</context></context-group>
</trans-unit>
- <trans-unit id="_msg200">
+ <trans-unit id="_msg210">
<source xml:space="preserve">Copy bytes</source>
<context-group purpose="location"><context context-type="linenumber">72</context></context-group>
</trans-unit>
- <trans-unit id="_msg201">
+ <trans-unit id="_msg211">
<source xml:space="preserve">Copy dust</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
</trans-unit>
- <trans-unit id="_msg202">
+ <trans-unit id="_msg212">
<source xml:space="preserve">Copy change</source>
<context-group purpose="location"><context context-type="linenumber">74</context></context-group>
</trans-unit>
- <trans-unit id="_msg203">
+ <trans-unit id="_msg213">
<source xml:space="preserve">(%1 locked)</source>
<context-group purpose="location"><context context-type="linenumber">380</context></context-group>
</trans-unit>
- <trans-unit id="_msg204">
+ <trans-unit id="_msg214">
<source xml:space="preserve">yes</source>
- <context-group purpose="location"><context context-type="linenumber">535</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">534</context></context-group>
</trans-unit>
- <trans-unit id="_msg205">
+ <trans-unit id="_msg215">
<source xml:space="preserve">no</source>
- <context-group purpose="location"><context context-type="linenumber">535</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">534</context></context-group>
</trans-unit>
- <trans-unit id="_msg206">
+ <trans-unit id="_msg216">
<source xml:space="preserve">This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <context-group purpose="location"><context context-type="linenumber">549</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">548</context></context-group>
</trans-unit>
- <trans-unit id="_msg207">
+ <trans-unit id="_msg217">
<source xml:space="preserve">Can vary +/- %1 satoshi(s) per input.</source>
- <context-group purpose="location"><context context-type="linenumber">554</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">553</context></context-group>
</trans-unit>
- <trans-unit id="_msg208">
+ <trans-unit id="_msg218">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">601</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">655</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">600</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">654</context></context-group>
</trans-unit>
- <trans-unit id="_msg209">
+ <trans-unit id="_msg219">
<source xml:space="preserve">change from %1 (%2)</source>
- <context-group purpose="location"><context context-type="linenumber">648</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">647</context></context-group>
</trans-unit>
- <trans-unit id="_msg210">
+ <trans-unit id="_msg220">
<source xml:space="preserve">(change)</source>
- <context-group purpose="location"><context context-type="linenumber">649</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">648</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../walletcontroller.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CreateWalletActivity">
- <trans-unit id="_msg211">
+ <trans-unit id="_msg221">
<source xml:space="preserve">Create Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">243</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">244</context></context-group>
<note annotates="source" from="developer">Title of window indicating the progress of creation of a new wallet.</note>
</trans-unit>
- <trans-unit id="_msg212">
+ <trans-unit id="_msg222">
<source xml:space="preserve">Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
- <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">247</context></context-group>
<note annotates="source" from="developer">Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</note>
</trans-unit>
- <trans-unit id="_msg213">
+ <trans-unit id="_msg223">
<source xml:space="preserve">Create wallet failed</source>
- <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">280</context></context-group>
</trans-unit>
- <trans-unit id="_msg214">
+ <trans-unit id="_msg224">
<source xml:space="preserve">Create wallet warning</source>
- <context-group purpose="location"><context context-type="linenumber">277</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
</trans-unit>
- <trans-unit id="_msg215">
+ <trans-unit id="_msg225">
<source xml:space="preserve">Can&apos;t list signers</source>
- <context-group purpose="location"><context context-type="linenumber">293</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">298</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg226">
+ <source xml:space="preserve">Too many external signers found</source>
+ <context-group purpose="location"><context context-type="linenumber">301</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="LoadWalletsActivity">
- <trans-unit id="_msg216">
+ <trans-unit id="_msg227">
<source xml:space="preserve">Load Wallets</source>
- <context-group purpose="location"><context context-type="linenumber">362</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">375</context></context-group>
<note annotates="source" from="developer">Title of progress window which is displayed when wallets are being loaded.</note>
</trans-unit>
- <trans-unit id="_msg217">
+ <trans-unit id="_msg228">
<source xml:space="preserve">Loading wallets…</source>
- <context-group purpose="location"><context context-type="linenumber">365</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">378</context></context-group>
<note annotates="source" from="developer">Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</note>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="OpenWalletActivity">
- <trans-unit id="_msg218">
+ <trans-unit id="_msg229">
<source xml:space="preserve">Open wallet failed</source>
- <context-group purpose="location"><context context-type="linenumber">323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
</trans-unit>
- <trans-unit id="_msg219">
+ <trans-unit id="_msg230">
<source xml:space="preserve">Open wallet warning</source>
- <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
- <trans-unit id="_msg220">
+ <trans-unit id="_msg231">
<source xml:space="preserve">default wallet</source>
- <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">344</context></context-group>
</trans-unit>
- <trans-unit id="_msg221">
+ <trans-unit id="_msg232">
<source xml:space="preserve">Open Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">348</context></context-group>
<note annotates="source" from="developer">Title of window indicating the progress of opening of a wallet.</note>
</trans-unit>
- <trans-unit id="_msg222">
+ <trans-unit id="_msg233">
<source xml:space="preserve">Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
- <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">351</context></context-group>
<note annotates="source" from="developer">Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</note>
</trans-unit>
</group>
+ <group restype="x-trolltech-linguist-context" resname="RestoreWalletActivity">
+ <trans-unit id="_msg234">
+ <source xml:space="preserve">Restore Wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">400</context></context-group>
+ <note annotates="source" from="developer">Title of progress window which is displayed when wallets are being restored.</note>
+ </trans-unit>
+ <trans-unit id="_msg235">
+ <source xml:space="preserve">Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <context-group purpose="location"><context context-type="linenumber">403</context></context-group>
+ <note annotates="source" from="developer">Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</note>
+ </trans-unit>
+ <trans-unit id="_msg236">
+ <source xml:space="preserve">Restore wallet failed</source>
+ <context-group purpose="location"><context context-type="linenumber">422</context></context-group>
+ <note annotates="source" from="developer">Title of message box which is displayed when the wallet could not be restored.</note>
+ </trans-unit>
+ <trans-unit id="_msg237">
+ <source xml:space="preserve">Restore wallet warning</source>
+ <context-group purpose="location"><context context-type="linenumber">425</context></context-group>
+ <note annotates="source" from="developer">Title of message box which is displayed when the wallet is restored with some warning.</note>
+ </trans-unit>
+ <trans-unit id="_msg238">
+ <source xml:space="preserve">Restore wallet message</source>
+ <context-group purpose="location"><context context-type="linenumber">428</context></context-group>
+ <note annotates="source" from="developer">Title of message box which is displayed when the wallet is successfully restored.</note>
+ </trans-unit>
+ </group>
<group restype="x-trolltech-linguist-context" resname="WalletController">
- <trans-unit id="_msg223">
+ <trans-unit id="_msg239">
<source xml:space="preserve">Close wallet</source>
- <context-group purpose="location"><context context-type="linenumber">83</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
</trans-unit>
- <trans-unit id="_msg224">
+ <trans-unit id="_msg240">
<source xml:space="preserve">Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
- <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">85</context></context-group>
</trans-unit>
- <trans-unit id="_msg225">
+ <trans-unit id="_msg241">
<source xml:space="preserve">Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
- <context-group purpose="location"><context context-type="linenumber">85</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">86</context></context-group>
</trans-unit>
- <trans-unit id="_msg226">
+ <trans-unit id="_msg242">
<source xml:space="preserve">Close all wallets</source>
- <context-group purpose="location"><context context-type="linenumber">98</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg227">
+ <trans-unit id="_msg243">
<source xml:space="preserve">Are you sure you wish to close all wallets?</source>
- <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/createwalletdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CreateWalletDialog">
- <trans-unit id="_msg228">
+ <trans-unit id="_msg244">
<source xml:space="preserve">Create Wallet</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg229">
+ <trans-unit id="_msg245">
<source xml:space="preserve">Wallet Name</source>
<context-group purpose="location"><context context-type="linenumber">25</context></context-group>
</trans-unit>
- <trans-unit id="_msg230">
+ <trans-unit id="_msg246">
<source xml:space="preserve">Wallet</source>
<context-group purpose="location"><context context-type="linenumber">38</context></context-group>
</trans-unit>
- <trans-unit id="_msg231">
+ <trans-unit id="_msg247">
<source xml:space="preserve">Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
<context-group purpose="location"><context context-type="linenumber">47</context></context-group>
</trans-unit>
- <trans-unit id="_msg232">
+ <trans-unit id="_msg248">
<source xml:space="preserve">Encrypt Wallet</source>
<context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg233">
+ <trans-unit id="_msg249">
<source xml:space="preserve">Advanced Options</source>
<context-group purpose="location"><context context-type="linenumber">76</context></context-group>
</trans-unit>
- <trans-unit id="_msg234">
+ <trans-unit id="_msg250">
<source xml:space="preserve">Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets.</source>
<context-group purpose="location"><context context-type="linenumber">85</context></context-group>
</trans-unit>
- <trans-unit id="_msg235">
+ <trans-unit id="_msg251">
<source xml:space="preserve">Disable Private Keys</source>
<context-group purpose="location"><context context-type="linenumber">88</context></context-group>
</trans-unit>
- <trans-unit id="_msg236">
+ <trans-unit id="_msg252">
<source xml:space="preserve">Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time.</source>
<context-group purpose="location"><context context-type="linenumber">95</context></context-group>
</trans-unit>
- <trans-unit id="_msg237">
+ <trans-unit id="_msg253">
<source xml:space="preserve">Make Blank Wallet</source>
<context-group purpose="location"><context context-type="linenumber">98</context></context-group>
</trans-unit>
- <trans-unit id="_msg238">
+ <trans-unit id="_msg254">
<source xml:space="preserve">Use descriptors for scriptPubKey management</source>
<context-group purpose="location"><context context-type="linenumber">105</context></context-group>
</trans-unit>
- <trans-unit id="_msg239">
+ <trans-unit id="_msg255">
<source xml:space="preserve">Descriptor Wallet</source>
<context-group purpose="location"><context context-type="linenumber">108</context></context-group>
</trans-unit>
- <trans-unit id="_msg240">
+ <trans-unit id="_msg256">
<source xml:space="preserve">Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
<context-group purpose="location"><context context-type="linenumber">118</context></context-group>
</trans-unit>
- <trans-unit id="_msg241">
+ <trans-unit id="_msg257">
<source xml:space="preserve">External signer</source>
<context-group purpose="location"><context context-type="linenumber">121</context></context-group>
</trans-unit>
@@ -1069,15 +1146,15 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../createwalletdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="CreateWalletDialog">
- <trans-unit id="_msg242">
+ <trans-unit id="_msg258">
<source xml:space="preserve">Create</source>
<context-group purpose="location"><context context-type="linenumber">22</context></context-group>
</trans-unit>
- <trans-unit id="_msg243">
+ <trans-unit id="_msg259">
<source xml:space="preserve">Compiled without sqlite support (required for descriptor wallets)</source>
<context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
- <trans-unit id="_msg244">
+ <trans-unit id="_msg260">
<source xml:space="preserve">Compiled without external signing support (required for external signing)</source>
<context-group purpose="location"><context context-type="linenumber">104</context></context-group>
<note annotates="source" from="developer">&quot;External signing&quot; means using devices such as hardware wallets.</note>
@@ -1086,23 +1163,23 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../forms/editaddressdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="EditAddressDialog">
- <trans-unit id="_msg245">
+ <trans-unit id="_msg261">
<source xml:space="preserve">Edit Address</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg246">
+ <trans-unit id="_msg262">
<source xml:space="preserve">&amp;Label</source>
<context-group purpose="location"><context context-type="linenumber">25</context></context-group>
</trans-unit>
- <trans-unit id="_msg247">
+ <trans-unit id="_msg263">
<source xml:space="preserve">The label associated with this address list entry</source>
<context-group purpose="location"><context context-type="linenumber">35</context></context-group>
</trans-unit>
- <trans-unit id="_msg248">
+ <trans-unit id="_msg264">
<source xml:space="preserve">The address associated with this address list entry. This can only be modified for sending addresses.</source>
<context-group purpose="location"><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="_msg249">
+ <trans-unit id="_msg265">
<source xml:space="preserve">&amp;Address</source>
<context-group purpose="location"><context context-type="linenumber">42</context></context-group>
</trans-unit>
@@ -1110,35 +1187,35 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../editaddressdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="EditAddressDialog">
- <trans-unit id="_msg250">
+ <trans-unit id="_msg266">
<source xml:space="preserve">New sending address</source>
<context-group purpose="location"><context context-type="linenumber">29</context></context-group>
</trans-unit>
- <trans-unit id="_msg251">
+ <trans-unit id="_msg267">
<source xml:space="preserve">Edit receiving address</source>
<context-group purpose="location"><context context-type="linenumber">32</context></context-group>
</trans-unit>
- <trans-unit id="_msg252">
+ <trans-unit id="_msg268">
<source xml:space="preserve">Edit sending address</source>
<context-group purpose="location"><context context-type="linenumber">36</context></context-group>
</trans-unit>
- <trans-unit id="_msg253">
+ <trans-unit id="_msg269">
<source xml:space="preserve">The entered address &quot;%1&quot; is not a valid Bitcoin address.</source>
<context-group purpose="location"><context context-type="linenumber">113</context></context-group>
</trans-unit>
- <trans-unit id="_msg254">
+ <trans-unit id="_msg270">
<source xml:space="preserve">Address &quot;%1&quot; already exists as a receiving address with label &quot;%2&quot; and so cannot be added as a sending address.</source>
<context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg255">
+ <trans-unit id="_msg271">
<source xml:space="preserve">The entered address &quot;%1&quot; is already in the address book with label &quot;%2&quot;.</source>
<context-group purpose="location"><context context-type="linenumber">151</context></context-group>
</trans-unit>
- <trans-unit id="_msg256">
+ <trans-unit id="_msg272">
<source xml:space="preserve">Could not unlock wallet.</source>
<context-group purpose="location"><context context-type="linenumber">123</context></context-group>
</trans-unit>
- <trans-unit id="_msg257">
+ <trans-unit id="_msg273">
<source xml:space="preserve">New key generation failed.</source>
<context-group purpose="location"><context context-type="linenumber">128</context></context-group>
</trans-unit>
@@ -1146,75 +1223,90 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../intro.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="FreespaceChecker">
- <trans-unit id="_msg258">
+ <trans-unit id="_msg274">
<source xml:space="preserve">A new data directory will be created.</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
</trans-unit>
- <trans-unit id="_msg259">
+ <trans-unit id="_msg275">
<source xml:space="preserve">name</source>
<context-group purpose="location"><context context-type="linenumber">95</context></context-group>
</trans-unit>
- <trans-unit id="_msg260">
+ <trans-unit id="_msg276">
<source xml:space="preserve">Directory already exists. Add %1 if you intend to create a new directory here.</source>
<context-group purpose="location"><context context-type="linenumber">97</context></context-group>
</trans-unit>
- <trans-unit id="_msg261">
+ <trans-unit id="_msg277">
<source xml:space="preserve">Path already exists, and is not a directory.</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
- <trans-unit id="_msg262">
+ <trans-unit id="_msg278">
<source xml:space="preserve">Cannot create data directory here.</source>
<context-group purpose="location"><context context-type="linenumber">107</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="Intro">
- <trans-unit id="_msg263">
+ <trans-unit id="_msg279">
<source xml:space="preserve">Bitcoin</source>
<context-group purpose="location"><context context-type="linenumber">139</context></context-group>
</trans-unit>
- <trans-unit id="_msg264">
- <source xml:space="preserve">%1 GB of space available</source>
+ <group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">301</context></context-group>
- </trans-unit>
- <trans-unit id="_msg265">
- <source xml:space="preserve">(of %1 GB needed)</source>
+ <trans-unit id="_msg280[0]">
+ <source xml:space="preserve">%n GB of space available</source>
+ </trans-unit>
+ <trans-unit id="_msg280[1]">
+ <source xml:space="preserve">%n GB of space available</source>
+ </trans-unit>
+ </group>
+ <group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">303</context></context-group>
- </trans-unit>
- <trans-unit id="_msg266">
- <source xml:space="preserve">(%1 GB needed for full chain)</source>
+ <trans-unit id="_msg281[0]">
+ <source xml:space="preserve">(of %n GB needed)</source>
+ </trans-unit>
+ <trans-unit id="_msg281[1]">
+ <source xml:space="preserve">(of %n GB needed)</source>
+ </trans-unit>
+ </group>
+ <group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">306</context></context-group>
- </trans-unit>
- <trans-unit id="_msg267">
+ <trans-unit id="_msg282[0]">
+ <source xml:space="preserve">(%n GB needed for full chain)</source>
+ </trans-unit>
+ <trans-unit id="_msg282[1]">
+ <source xml:space="preserve">(%n GB needed for full chain)</source>
+ </trans-unit>
+ </group>
+ <trans-unit id="_msg283">
<source xml:space="preserve">At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<context-group purpose="location"><context context-type="linenumber">378</context></context-group>
</trans-unit>
- <trans-unit id="_msg268">
+ <trans-unit id="_msg284">
<source xml:space="preserve">Approximately %1 GB of data will be stored in this directory.</source>
<context-group purpose="location"><context context-type="linenumber">381</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
<context-group purpose="location"><context context-type="linenumber">390</context></context-group>
<note annotates="source" from="developer">Explanatory text on the capability of the current prune target.</note>
- <trans-unit id="_msg269[0]">
+ <trans-unit id="_msg285[0]">
<source xml:space="preserve">(sufficient to restore backups %n day(s) old)</source>
</trans-unit>
- <trans-unit id="_msg269[1]">
+ <trans-unit id="_msg285[1]">
<source xml:space="preserve">(sufficient to restore backups %n day(s) old)</source>
</trans-unit>
</group>
- <trans-unit id="_msg270">
+ <trans-unit id="_msg286">
<source xml:space="preserve">%1 will download and store a copy of the Bitcoin block chain.</source>
<context-group purpose="location"><context context-type="linenumber">392</context></context-group>
</trans-unit>
- <trans-unit id="_msg271">
+ <trans-unit id="_msg287">
<source xml:space="preserve">The wallet will also be stored in this directory.</source>
<context-group purpose="location"><context context-type="linenumber">394</context></context-group>
</trans-unit>
- <trans-unit id="_msg272">
+ <trans-unit id="_msg288">
<source xml:space="preserve">Error: Specified data directory &quot;%1&quot; cannot be created.</source>
<context-group purpose="location"><context context-type="linenumber">250</context></context-group>
</trans-unit>
- <trans-unit id="_msg273">
+ <trans-unit id="_msg289">
<source xml:space="preserve">Error</source>
<context-group purpose="location"><context context-type="linenumber">280</context></context-group>
</trans-unit>
@@ -1222,25 +1314,25 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../utilitydialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="HelpMessageDialog">
- <trans-unit id="_msg274">
+ <trans-unit id="_msg290">
<source xml:space="preserve">version</source>
- <context-group purpose="location"><context context-type="linenumber">37</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">38</context></context-group>
</trans-unit>
- <trans-unit id="_msg275">
+ <trans-unit id="_msg291">
<source xml:space="preserve">About %1</source>
- <context-group purpose="location"><context context-type="linenumber">41</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">42</context></context-group>
</trans-unit>
- <trans-unit id="_msg276">
+ <trans-unit id="_msg292">
<source xml:space="preserve">Command-line options</source>
<context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="ShutdownWindow">
- <trans-unit id="_msg277">
+ <trans-unit id="_msg293">
<source xml:space="preserve">%1 is shutting down…</source>
<context-group purpose="location"><context context-type="linenumber">145</context></context-group>
</trans-unit>
- <trans-unit id="_msg278">
+ <trans-unit id="_msg294">
<source xml:space="preserve">Do not shut down the computer until this window disappears.</source>
<context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
@@ -1248,47 +1340,47 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../forms/intro.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="Intro">
- <trans-unit id="_msg279">
+ <trans-unit id="_msg295">
<source xml:space="preserve">Welcome</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg280">
+ <trans-unit id="_msg296">
<source xml:space="preserve">Welcome to %1.</source>
<context-group purpose="location"><context context-type="linenumber">23</context></context-group>
</trans-unit>
- <trans-unit id="_msg281">
+ <trans-unit id="_msg297">
<source xml:space="preserve">As this is the first time the program is launched, you can choose where %1 will store its data.</source>
<context-group purpose="location"><context context-type="linenumber">49</context></context-group>
</trans-unit>
- <trans-unit id="_msg282">
- <source xml:space="preserve">When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <context-group purpose="location"><context context-type="linenumber">206</context></context-group>
- </trans-unit>
- <trans-unit id="_msg283">
+ <trans-unit id="_msg298">
<source xml:space="preserve">Limit block chain storage to</source>
<context-group purpose="location"><context context-type="linenumber">238</context></context-group>
</trans-unit>
- <trans-unit id="_msg284">
+ <trans-unit id="_msg299">
<source xml:space="preserve">Reverting this setting requires re-downloading the entire blockchain. It is faster to download the full chain first and prune it later. Disables some advanced features.</source>
<context-group purpose="location"><context context-type="linenumber">241</context></context-group>
</trans-unit>
- <trans-unit id="_msg285">
+ <trans-unit id="_msg300">
<source xml:space="preserve"> GB</source>
<context-group purpose="location"><context context-type="linenumber">248</context></context-group>
</trans-unit>
- <trans-unit id="_msg286">
+ <trans-unit id="_msg301">
<source xml:space="preserve">This initial synchronisation is very demanding, and may expose hardware problems with your computer that had previously gone unnoticed. Each time you run %1, it will continue downloading where it left off.</source>
<context-group purpose="location"><context context-type="linenumber">216</context></context-group>
</trans-unit>
- <trans-unit id="_msg287">
+ <trans-unit id="_msg302">
+ <source xml:space="preserve">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="_msg303">
<source xml:space="preserve">If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg288">
+ <trans-unit id="_msg304">
<source xml:space="preserve">Use the default data directory</source>
<context-group purpose="location"><context context-type="linenumber">66</context></context-group>
</trans-unit>
- <trans-unit id="_msg289">
+ <trans-unit id="_msg305">
<source xml:space="preserve">Use a custom data directory:</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
</trans-unit>
@@ -1296,54 +1388,54 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../forms/modaloverlay.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="ModalOverlay">
- <trans-unit id="_msg290">
+ <trans-unit id="_msg306">
<source xml:space="preserve">Form</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg291">
+ <trans-unit id="_msg307">
<source xml:space="preserve">Recent transactions may not yet be visible, and therefore your wallet&apos;s balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
<context-group purpose="location"><context context-type="linenumber">133</context></context-group>
</trans-unit>
- <trans-unit id="_msg292">
+ <trans-unit id="_msg308">
<source xml:space="preserve">Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
<context-group purpose="location"><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="_msg293">
+ <trans-unit id="_msg309">
<source xml:space="preserve">Number of blocks left</source>
<context-group purpose="location"><context context-type="linenumber">215</context></context-group>
</trans-unit>
- <trans-unit id="_msg294">
+ <trans-unit id="_msg310">
<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>
+ <context-group purpose="location"><context context-type="sourcefile">../modaloverlay.cpp</context><context context-type="linenumber">155</context></context-group>
</trans-unit>
- <trans-unit id="_msg295">
+ <trans-unit id="_msg311">
<source xml:space="preserve">calculating…</source>
<context-group purpose="location"><context context-type="linenumber">292</context></context-group>
<context-group purpose="location"><context context-type="linenumber">312</context></context-group>
</trans-unit>
- <trans-unit id="_msg296">
+ <trans-unit id="_msg312">
<source xml:space="preserve">Last block time</source>
<context-group purpose="location"><context context-type="linenumber">235</context></context-group>
</trans-unit>
- <trans-unit id="_msg297">
+ <trans-unit id="_msg313">
<source xml:space="preserve">Progress</source>
<context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg298">
+ <trans-unit id="_msg314">
<source xml:space="preserve">Progress increase per hour</source>
<context-group purpose="location"><context context-type="linenumber">285</context></context-group>
</trans-unit>
- <trans-unit id="_msg299">
+ <trans-unit id="_msg315">
<source xml:space="preserve">Estimated time left until synced</source>
<context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
- <trans-unit id="_msg300">
+ <trans-unit id="_msg316">
<source xml:space="preserve">Hide</source>
<context-group purpose="location"><context context-type="linenumber">342</context></context-group>
</trans-unit>
- <trans-unit id="_msg301">
+ <trans-unit id="_msg317">
<source xml:space="preserve">Esc</source>
<context-group purpose="location"><context context-type="linenumber">345</context></context-group>
</trans-unit>
@@ -1351,33 +1443,37 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../modaloverlay.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="ModalOverlay">
- <trans-unit id="_msg302">
+ <trans-unit id="_msg318">
<source xml:space="preserve">%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
<context-group purpose="location"><context context-type="linenumber">34</context></context-group>
</trans-unit>
- <trans-unit id="_msg303">
+ <trans-unit id="_msg319">
<source xml:space="preserve">Unknown. Syncing Headers (%1, %2%)…</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>
+ </trans-unit>
+ <trans-unit id="_msg320">
+ <source xml:space="preserve">Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <context-group purpose="location"><context context-type="linenumber">166</context></context-group>
</trans-unit>
</group>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg304">
+ <trans-unit id="_msg321">
<source xml:space="preserve">unknown</source>
- <context-group purpose="location"><context context-type="linenumber">123</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">126</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/openuridialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OpenURIDialog">
- <trans-unit id="_msg305">
+ <trans-unit id="_msg322">
<source xml:space="preserve">Open bitcoin URI</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg306">
+ <trans-unit id="_msg323">
<source xml:space="preserve">URI:</source>
<context-group purpose="location"><context context-type="linenumber">22</context></context-group>
</trans-unit>
- <trans-unit id="_msg307">
+ <trans-unit id="_msg324">
<source xml:space="preserve">Paste address from clipboard</source>
<context-group purpose="location"><context context-type="linenumber">36</context></context-group>
<note annotates="source" from="developer">Tooltip text for button that allows you to paste an address that is in your clipboard.</note>
@@ -1386,310 +1482,310 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../forms/optionsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OptionsDialog">
- <trans-unit id="_msg308">
+ <trans-unit id="_msg325">
<source xml:space="preserve">Options</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg309">
+ <trans-unit id="_msg326">
<source xml:space="preserve">&amp;Main</source>
<context-group purpose="location"><context context-type="linenumber">27</context></context-group>
</trans-unit>
- <trans-unit id="_msg310">
+ <trans-unit id="_msg327">
<source xml:space="preserve">Automatically start %1 after logging in to the system.</source>
<context-group purpose="location"><context context-type="linenumber">33</context></context-group>
</trans-unit>
- <trans-unit id="_msg311">
+ <trans-unit id="_msg328">
<source xml:space="preserve">&amp;Start %1 on system login</source>
<context-group purpose="location"><context context-type="linenumber">36</context></context-group>
</trans-unit>
- <trans-unit id="_msg312">
+ <trans-unit id="_msg329">
<source xml:space="preserve">Enabling pruning significantly reduces the disk space required to store transactions. All blocks are still fully validated. Reverting this setting requires re-downloading the entire blockchain.</source>
<context-group purpose="location"><context context-type="linenumber">58</context></context-group>
</trans-unit>
- <trans-unit id="_msg313">
+ <trans-unit id="_msg330">
<source xml:space="preserve">Size of &amp;database cache</source>
<context-group purpose="location"><context context-type="linenumber">111</context></context-group>
</trans-unit>
- <trans-unit id="_msg314">
+ <trans-unit id="_msg331">
<source xml:space="preserve">Number of script &amp;verification threads</source>
<context-group purpose="location"><context context-type="linenumber">157</context></context-group>
</trans-unit>
- <trans-unit id="_msg315">
+ <trans-unit id="_msg332">
<source xml:space="preserve">IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
<context-group purpose="location"><context context-type="linenumber">388</context></context-group>
<context-group purpose="location"><context context-type="linenumber">575</context></context-group>
</trans-unit>
- <trans-unit id="_msg316">
+ <trans-unit id="_msg333">
<source xml:space="preserve">Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
<context-group purpose="location"><context context-type="linenumber">457</context></context-group>
<context-group purpose="location"><context context-type="linenumber">480</context></context-group>
<context-group purpose="location"><context context-type="linenumber">503</context></context-group>
</trans-unit>
- <trans-unit id="_msg317">
+ <trans-unit id="_msg334">
<source xml:space="preserve">Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Exit in the menu.</source>
<context-group purpose="location"><context context-type="linenumber">672</context></context-group>
</trans-unit>
- <trans-unit id="_msg318">
+ <trans-unit id="_msg335">
+ <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="_msg336">
<source xml:space="preserve">Open the %1 configuration file from the working directory.</source>
<context-group purpose="location"><context context-type="linenumber">944</context></context-group>
</trans-unit>
- <trans-unit id="_msg319">
+ <trans-unit id="_msg337">
<source xml:space="preserve">Open Configuration File</source>
<context-group purpose="location"><context context-type="linenumber">947</context></context-group>
</trans-unit>
- <trans-unit id="_msg320">
+ <trans-unit id="_msg338">
<source xml:space="preserve">Reset all client options to default.</source>
<context-group purpose="location"><context context-type="linenumber">957</context></context-group>
</trans-unit>
- <trans-unit id="_msg321">
+ <trans-unit id="_msg339">
<source xml:space="preserve">&amp;Reset Options</source>
<context-group purpose="location"><context context-type="linenumber">960</context></context-group>
</trans-unit>
- <trans-unit id="_msg322">
+ <trans-unit id="_msg340">
<source xml:space="preserve">&amp;Network</source>
<context-group purpose="location"><context context-type="linenumber">315</context></context-group>
</trans-unit>
- <trans-unit id="_msg323">
+ <trans-unit id="_msg341">
<source xml:space="preserve">Prune &amp;block storage to</source>
<context-group purpose="location"><context context-type="linenumber">61</context></context-group>
</trans-unit>
- <trans-unit id="_msg324">
+ <trans-unit id="_msg342">
<source xml:space="preserve">GB</source>
<context-group purpose="location"><context context-type="linenumber">71</context></context-group>
</trans-unit>
- <trans-unit id="_msg325">
+ <trans-unit id="_msg343">
<source xml:space="preserve">Reverting this setting requires re-downloading the entire blockchain.</source>
<context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg326">
+ <trans-unit id="_msg344">
<source xml:space="preserve">Maximum database cache size. A larger cache can contribute to faster sync, after which the benefit is less pronounced for most use cases. Lowering the cache size will reduce memory usage. Unused mempool memory is shared for this cache.</source>
<context-group purpose="location"><context context-type="linenumber">108</context></context-group>
<note annotates="source" from="developer">Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</note>
</trans-unit>
- <trans-unit id="_msg327">
+ <trans-unit id="_msg345">
<source xml:space="preserve">MiB</source>
<context-group purpose="location"><context context-type="linenumber">127</context></context-group>
</trans-unit>
- <trans-unit id="_msg328">
+ <trans-unit id="_msg346">
<source xml:space="preserve">Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
<context-group purpose="location"><context context-type="linenumber">154</context></context-group>
<note annotates="source" from="developer">Tooltip text for Options window setting that sets the number of script verification threads. Explains that negative values mean to leave these many cores free to the system.</note>
</trans-unit>
- <trans-unit id="_msg329">
+ <trans-unit id="_msg347">
<source xml:space="preserve">(0 = auto, &lt;0 = leave that many cores free)</source>
<context-group purpose="location"><context context-type="linenumber">170</context></context-group>
</trans-unit>
- <trans-unit id="_msg330">
+ <trans-unit id="_msg348">
<source xml:space="preserve">This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
<context-group purpose="location"><context context-type="linenumber">192</context></context-group>
<note annotates="source" from="developer">Tooltip text for Options window setting that enables the RPC server.</note>
</trans-unit>
- <trans-unit id="_msg331">
+ <trans-unit id="_msg349">
<source xml:space="preserve">Enable R&amp;PC server</source>
<context-group purpose="location"><context context-type="linenumber">195</context></context-group>
<note annotates="source" from="developer">An Options window setting to enable the RPC server.</note>
</trans-unit>
- <trans-unit id="_msg332">
+ <trans-unit id="_msg350">
<source xml:space="preserve">W&amp;allet</source>
<context-group purpose="location"><context context-type="linenumber">216</context></context-group>
</trans-unit>
- <trans-unit id="_msg333">
+ <trans-unit id="_msg351">
<source xml:space="preserve">Whether to set subtract fee from amount as default or not.</source>
<context-group purpose="location"><context context-type="linenumber">222</context></context-group>
<note annotates="source" from="developer">Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</note>
</trans-unit>
- <trans-unit id="_msg334">
+ <trans-unit id="_msg352">
<source xml:space="preserve">Subtract &amp;fee from amount by default</source>
<context-group purpose="location"><context context-type="linenumber">225</context></context-group>
<note annotates="source" from="developer">An Options window setting to set subtracting the fee from a sending amount as default.</note>
</trans-unit>
- <trans-unit id="_msg335">
+ <trans-unit id="_msg353">
<source xml:space="preserve">Expert</source>
<context-group purpose="location"><context context-type="linenumber">232</context></context-group>
</trans-unit>
- <trans-unit id="_msg336">
+ <trans-unit id="_msg354">
<source xml:space="preserve">Enable coin &amp;control features</source>
<context-group purpose="location"><context context-type="linenumber">241</context></context-group>
</trans-unit>
- <trans-unit id="_msg337">
+ <trans-unit id="_msg355">
<source xml:space="preserve">If you disable the spending of unconfirmed change, the change from a transaction cannot be used until that transaction has at least one confirmation. This also affects how your balance is computed.</source>
<context-group purpose="location"><context context-type="linenumber">248</context></context-group>
</trans-unit>
- <trans-unit id="_msg338">
+ <trans-unit id="_msg356">
<source xml:space="preserve">&amp;Spend unconfirmed change</source>
<context-group purpose="location"><context context-type="linenumber">251</context></context-group>
</trans-unit>
- <trans-unit id="_msg339">
+ <trans-unit id="_msg357">
<source xml:space="preserve">Enable &amp;PSBT controls</source>
<context-group purpose="location"><context context-type="linenumber">258</context></context-group>
<note annotates="source" from="developer">An options window setting to enable PSBT controls.</note>
</trans-unit>
- <trans-unit id="_msg340">
+ <trans-unit id="_msg358">
<source xml:space="preserve">Whether to show PSBT controls.</source>
<context-group purpose="location"><context context-type="linenumber">261</context></context-group>
<note annotates="source" from="developer">Tooltip text for options window setting that enables PSBT controls.</note>
</trans-unit>
- <trans-unit id="_msg341">
+ <trans-unit id="_msg359">
<source xml:space="preserve">External Signer (e.g. hardware wallet)</source>
<context-group purpose="location"><context context-type="linenumber">271</context></context-group>
</trans-unit>
- <trans-unit id="_msg342">
+ <trans-unit id="_msg360">
<source xml:space="preserve">&amp;External signer script path</source>
<context-group purpose="location"><context context-type="linenumber">279</context></context-group>
</trans-unit>
- <trans-unit id="_msg343">
+ <trans-unit id="_msg361">
<source xml:space="preserve">Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
<context-group purpose="location"><context context-type="linenumber">289</context></context-group>
</trans-unit>
- <trans-unit id="_msg344">
+ <trans-unit id="_msg362">
<source xml:space="preserve">Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg345">
+ <trans-unit id="_msg363">
<source xml:space="preserve">Map port using &amp;UPnP</source>
<context-group purpose="location"><context context-type="linenumber">324</context></context-group>
</trans-unit>
- <trans-unit id="_msg346">
+ <trans-unit id="_msg364">
<source xml:space="preserve">Automatically open the Bitcoin client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random.</source>
<context-group purpose="location"><context context-type="linenumber">331</context></context-group>
</trans-unit>
- <trans-unit id="_msg347">
+ <trans-unit id="_msg365">
<source xml:space="preserve">Map port using NA&amp;T-PMP</source>
<context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
- <trans-unit id="_msg348">
+ <trans-unit id="_msg366">
<source xml:space="preserve">Accept connections from outside.</source>
<context-group purpose="location"><context context-type="linenumber">341</context></context-group>
</trans-unit>
- <trans-unit id="_msg349">
+ <trans-unit id="_msg367">
<source xml:space="preserve">Allow incomin&amp;g connections</source>
<context-group purpose="location"><context context-type="linenumber">344</context></context-group>
</trans-unit>
- <trans-unit id="_msg350">
+ <trans-unit id="_msg368">
<source xml:space="preserve">Connect to the Bitcoin network through a SOCKS5 proxy.</source>
<context-group purpose="location"><context context-type="linenumber">351</context></context-group>
</trans-unit>
- <trans-unit id="_msg351">
+ <trans-unit id="_msg369">
<source xml:space="preserve">&amp;Connect through SOCKS5 proxy (default proxy):</source>
<context-group purpose="location"><context context-type="linenumber">354</context></context-group>
</trans-unit>
- <trans-unit id="_msg352">
+ <trans-unit id="_msg370">
<source xml:space="preserve">Proxy &amp;IP:</source>
<context-group purpose="location"><context context-type="linenumber">363</context></context-group>
<context-group purpose="location"><context context-type="linenumber">550</context></context-group>
</trans-unit>
- <trans-unit id="_msg353">
+ <trans-unit id="_msg371">
<source xml:space="preserve">&amp;Port:</source>
<context-group purpose="location"><context context-type="linenumber">395</context></context-group>
<context-group purpose="location"><context context-type="linenumber">582</context></context-group>
</trans-unit>
- <trans-unit id="_msg354">
+ <trans-unit id="_msg372">
<source xml:space="preserve">Port of the proxy (e.g. 9050)</source>
<context-group purpose="location"><context context-type="linenumber">420</context></context-group>
<context-group purpose="location"><context context-type="linenumber">607</context></context-group>
</trans-unit>
- <trans-unit id="_msg355">
+ <trans-unit id="_msg373">
<source xml:space="preserve">Used for reaching peers via:</source>
<context-group purpose="location"><context context-type="linenumber">444</context></context-group>
</trans-unit>
- <trans-unit id="_msg356">
+ <trans-unit id="_msg374">
<source xml:space="preserve">IPv4</source>
<context-group purpose="location"><context context-type="linenumber">467</context></context-group>
</trans-unit>
- <trans-unit id="_msg357">
+ <trans-unit id="_msg375">
<source xml:space="preserve">IPv6</source>
<context-group purpose="location"><context context-type="linenumber">490</context></context-group>
</trans-unit>
- <trans-unit id="_msg358">
+ <trans-unit id="_msg376">
<source xml:space="preserve">Tor</source>
<context-group purpose="location"><context context-type="linenumber">513</context></context-group>
</trans-unit>
- <trans-unit id="_msg359">
+ <trans-unit id="_msg377">
<source xml:space="preserve">&amp;Window</source>
<context-group purpose="location"><context context-type="linenumber">643</context></context-group>
</trans-unit>
- <trans-unit id="_msg360">
+ <trans-unit id="_msg378">
<source xml:space="preserve">Show the icon in the system tray.</source>
<context-group purpose="location"><context context-type="linenumber">649</context></context-group>
</trans-unit>
- <trans-unit id="_msg361">
+ <trans-unit id="_msg379">
<source xml:space="preserve">&amp;Show tray icon</source>
<context-group purpose="location"><context context-type="linenumber">652</context></context-group>
</trans-unit>
- <trans-unit id="_msg362">
+ <trans-unit id="_msg380">
<source xml:space="preserve">Show only a tray icon after minimizing the window.</source>
<context-group purpose="location"><context context-type="linenumber">662</context></context-group>
</trans-unit>
- <trans-unit id="_msg363">
+ <trans-unit id="_msg381">
<source xml:space="preserve">&amp;Minimize to the tray instead of the taskbar</source>
<context-group purpose="location"><context context-type="linenumber">665</context></context-group>
</trans-unit>
- <trans-unit id="_msg364">
+ <trans-unit id="_msg382">
<source xml:space="preserve">M&amp;inimize on close</source>
<context-group purpose="location"><context context-type="linenumber">675</context></context-group>
</trans-unit>
- <trans-unit id="_msg365">
+ <trans-unit id="_msg383">
<source xml:space="preserve">&amp;Display</source>
<context-group purpose="location"><context context-type="linenumber">696</context></context-group>
</trans-unit>
- <trans-unit id="_msg366">
+ <trans-unit id="_msg384">
<source xml:space="preserve">User Interface &amp;language:</source>
<context-group purpose="location"><context context-type="linenumber">704</context></context-group>
</trans-unit>
- <trans-unit id="_msg367">
+ <trans-unit id="_msg385">
<source xml:space="preserve">The user interface language can be set here. This setting will take effect after restarting %1.</source>
<context-group purpose="location"><context context-type="linenumber">717</context></context-group>
</trans-unit>
- <trans-unit id="_msg368">
+ <trans-unit id="_msg386">
<source xml:space="preserve">&amp;Unit to show amounts in:</source>
<context-group purpose="location"><context context-type="linenumber">728</context></context-group>
</trans-unit>
- <trans-unit id="_msg369">
+ <trans-unit id="_msg387">
<source xml:space="preserve">Choose the default subdivision unit to show in the interface and when sending coins.</source>
<context-group purpose="location"><context context-type="linenumber">741</context></context-group>
</trans-unit>
- <trans-unit id="_msg370">
+ <trans-unit id="_msg388">
<source xml:space="preserve">Third-party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.</source>
<context-group purpose="location"><context context-type="linenumber">752</context></context-group>
<context-group purpose="location"><context context-type="linenumber">765</context></context-group>
</trans-unit>
- <trans-unit id="_msg371">
+ <trans-unit id="_msg389">
<source xml:space="preserve">&amp;Third-party transaction URLs</source>
<context-group purpose="location"><context context-type="linenumber">755</context></context-group>
</trans-unit>
- <trans-unit id="_msg372">
+ <trans-unit id="_msg390">
<source xml:space="preserve">Whether to show coin control features or not.</source>
<context-group purpose="location"><context context-type="linenumber">238</context></context-group>
</trans-unit>
- <trans-unit id="_msg373">
+ <trans-unit id="_msg391">
<source xml:space="preserve">Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
<context-group purpose="location"><context context-type="linenumber">538</context></context-group>
</trans-unit>
- <trans-unit id="_msg374">
+ <trans-unit id="_msg392">
<source xml:space="preserve">Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
<context-group purpose="location"><context context-type="linenumber">541</context></context-group>
</trans-unit>
- <trans-unit id="_msg375">
+ <trans-unit id="_msg393">
<source xml:space="preserve">Monospaced font in the Overview tab:</source>
<context-group purpose="location"><context context-type="linenumber">777</context></context-group>
</trans-unit>
- <trans-unit id="_msg376">
+ <trans-unit id="_msg394">
<source xml:space="preserve">embedded &quot;%1&quot;</source>
<context-group purpose="location"><context context-type="linenumber">785</context></context-group>
</trans-unit>
- <trans-unit id="_msg377">
+ <trans-unit id="_msg395">
<source xml:space="preserve">closest matching &quot;%1&quot;</source>
<context-group purpose="location"><context context-type="linenumber">834</context></context-group>
</trans-unit>
- <trans-unit id="_msg378">
- <source xml:space="preserve">Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <context-group purpose="location"><context context-type="linenumber">899</context></context-group>
- </trans-unit>
- <trans-unit id="_msg379">
+ <trans-unit id="_msg396">
<source xml:space="preserve">&amp;OK</source>
<context-group purpose="location"><context context-type="linenumber">1040</context></context-group>
</trans-unit>
- <trans-unit id="_msg380">
+ <trans-unit id="_msg397">
<source xml:space="preserve">&amp;Cancel</source>
<context-group purpose="location"><context context-type="linenumber">1053</context></context-group>
</trans-unit>
@@ -1697,140 +1793,156 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../optionsdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OptionsDialog">
- <trans-unit id="_msg381">
+ <trans-unit id="_msg398">
<source xml:space="preserve">Compiled without external signing support (required for external signing)</source>
- <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
<note annotates="source" from="developer">&quot;External signing&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg382">
+ <trans-unit id="_msg399">
<source xml:space="preserve">default</source>
- <context-group purpose="location"><context context-type="linenumber">111</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
</trans-unit>
- <trans-unit id="_msg383">
+ <trans-unit id="_msg400">
<source xml:space="preserve">none</source>
- <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
</trans-unit>
- <trans-unit id="_msg384">
+ <trans-unit id="_msg401">
<source xml:space="preserve">Confirm options reset</source>
- <context-group purpose="location"><context context-type="linenumber">289</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">301</context></context-group>
+ <note annotates="source" from="developer">Window title text of pop-up window shown when the user has chosen to reset options.</note>
</trans-unit>
- <trans-unit id="_msg385">
+ <trans-unit id="_msg402">
<source xml:space="preserve">Client restart required to activate changes.</source>
- <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">360</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">371</context></context-group>
+ <note annotates="source" from="developer">Text explaining that the settings changed will not come into effect until the client is restarted.</note>
</trans-unit>
- <trans-unit id="_msg386">
+ <trans-unit id="_msg403">
+ <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="_msg404">
<source xml:space="preserve">Client will be shut down. Do you want to proceed?</source>
- <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
+ <note annotates="source" from="developer">Text asking the user to confirm if they would like to proceed with a client shutdown.</note>
</trans-unit>
- <trans-unit id="_msg387">
+ <trans-unit id="_msg405">
<source xml:space="preserve">Configuration options</source>
- <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">319</context></context-group>
<note annotates="source" from="developer">Window title text of pop-up box that allows opening up of configuration file.</note>
</trans-unit>
- <trans-unit id="_msg388">
+ <trans-unit id="_msg406">
<source xml:space="preserve">The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</source>
- <context-group purpose="location"><context context-type="linenumber">311</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">322</context></context-group>
<note annotates="source" from="developer">Explanatory text about the priority order of instructions considered by client. The order from high to low being: command-line, configuration file, GUI settings.</note>
</trans-unit>
- <trans-unit id="_msg389">
+ <trans-unit id="_msg407">
<source xml:space="preserve">Continue</source>
- <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
</trans-unit>
- <trans-unit id="_msg390">
+ <trans-unit id="_msg408">
<source xml:space="preserve">Cancel</source>
- <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
- <trans-unit id="_msg391">
+ <trans-unit id="_msg409">
<source xml:space="preserve">Error</source>
- <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg392">
+ <trans-unit id="_msg410">
<source xml:space="preserve">The configuration file could not be opened.</source>
- <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg393">
+ <trans-unit id="_msg411">
<source xml:space="preserve">This change would require a client restart.</source>
- <context-group purpose="location"><context context-type="linenumber">364</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">375</context></context-group>
</trans-unit>
- <trans-unit id="_msg394">
+ <trans-unit id="_msg412">
<source xml:space="preserve">The supplied proxy address is invalid.</source>
- <context-group purpose="location"><context context-type="linenumber">392</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">403</context></context-group>
+ </trans-unit>
+ </group>
+ </body></file>
+ <file original="../optionsmodel.cpp" datatype="cpp" source-language="en"><body>
+ <group restype="x-trolltech-linguist-context" resname="OptionsModel">
+ <trans-unit id="_msg413">
+ <source xml:space="preserve">Could not read setting &quot;%1&quot;, %2.</source>
+ <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/overviewpage.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OverviewPage">
- <trans-unit id="_msg395">
+ <trans-unit id="_msg414">
<source xml:space="preserve">Form</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg396">
+ <trans-unit id="_msg415">
<source xml:space="preserve">The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
<context-group purpose="location"><context context-type="linenumber">76</context></context-group>
<context-group purpose="location"><context context-type="linenumber">411</context></context-group>
</trans-unit>
- <trans-unit id="_msg397">
+ <trans-unit id="_msg416">
<source xml:space="preserve">Watch-only:</source>
<context-group purpose="location"><context context-type="linenumber">284</context></context-group>
</trans-unit>
- <trans-unit id="_msg398">
+ <trans-unit id="_msg417">
<source xml:space="preserve">Available:</source>
<context-group purpose="location"><context context-type="linenumber">294</context></context-group>
</trans-unit>
- <trans-unit id="_msg399">
+ <trans-unit id="_msg418">
<source xml:space="preserve">Your current spendable balance</source>
<context-group purpose="location"><context context-type="linenumber">304</context></context-group>
</trans-unit>
- <trans-unit id="_msg400">
+ <trans-unit id="_msg419">
<source xml:space="preserve">Pending:</source>
<context-group purpose="location"><context context-type="linenumber">339</context></context-group>
</trans-unit>
- <trans-unit id="_msg401">
+ <trans-unit id="_msg420">
<source xml:space="preserve">Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
<context-group purpose="location"><context context-type="linenumber">139</context></context-group>
</trans-unit>
- <trans-unit id="_msg402">
+ <trans-unit id="_msg421">
<source xml:space="preserve">Immature:</source>
<context-group purpose="location"><context context-type="linenumber">239</context></context-group>
</trans-unit>
- <trans-unit id="_msg403">
+ <trans-unit id="_msg422">
<source xml:space="preserve">Mined balance that has not yet matured</source>
<context-group purpose="location"><context context-type="linenumber">210</context></context-group>
</trans-unit>
- <trans-unit id="_msg404">
+ <trans-unit id="_msg423">
<source xml:space="preserve">Balances</source>
<context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
- <trans-unit id="_msg405">
+ <trans-unit id="_msg424">
<source xml:space="preserve">Total:</source>
<context-group purpose="location"><context context-type="linenumber">200</context></context-group>
</trans-unit>
- <trans-unit id="_msg406">
+ <trans-unit id="_msg425">
<source xml:space="preserve">Your current total balance</source>
<context-group purpose="location"><context context-type="linenumber">249</context></context-group>
</trans-unit>
- <trans-unit id="_msg407">
+ <trans-unit id="_msg426">
<source xml:space="preserve">Your current balance in watch-only addresses</source>
<context-group purpose="location"><context context-type="linenumber">323</context></context-group>
</trans-unit>
- <trans-unit id="_msg408">
+ <trans-unit id="_msg427">
<source xml:space="preserve">Spendable:</source>
<context-group purpose="location"><context context-type="linenumber">346</context></context-group>
</trans-unit>
- <trans-unit id="_msg409">
+ <trans-unit id="_msg428">
<source xml:space="preserve">Recent transactions</source>
<context-group purpose="location"><context context-type="linenumber">395</context></context-group>
</trans-unit>
- <trans-unit id="_msg410">
+ <trans-unit id="_msg429">
<source xml:space="preserve">Unconfirmed transactions to watch-only addresses</source>
<context-group purpose="location"><context context-type="linenumber">120</context></context-group>
</trans-unit>
- <trans-unit id="_msg411">
+ <trans-unit id="_msg430">
<source xml:space="preserve">Mined balance in watch-only addresses that has not yet matured</source>
<context-group purpose="location"><context context-type="linenumber">158</context></context-group>
</trans-unit>
- <trans-unit id="_msg412">
+ <trans-unit id="_msg431">
<source xml:space="preserve">Current total balance in watch-only addresses</source>
<context-group purpose="location"><context context-type="linenumber">268</context></context-group>
</trans-unit>
@@ -1838,35 +1950,35 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../overviewpage.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="OverviewPage">
- <trans-unit id="_msg413">
+ <trans-unit id="_msg432">
<source xml:space="preserve">Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
- <context-group purpose="location"><context context-type="linenumber">187</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">185</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/psbtoperationsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PSBTOperationsDialog">
- <trans-unit id="_msg414">
+ <trans-unit id="_msg433">
<source xml:space="preserve">Dialog</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg415">
+ <trans-unit id="_msg434">
<source xml:space="preserve">Sign Tx</source>
<context-group purpose="location"><context context-type="linenumber">86</context></context-group>
</trans-unit>
- <trans-unit id="_msg416">
+ <trans-unit id="_msg435">
<source xml:space="preserve">Broadcast Tx</source>
<context-group purpose="location"><context context-type="linenumber">102</context></context-group>
</trans-unit>
- <trans-unit id="_msg417">
+ <trans-unit id="_msg436">
<source xml:space="preserve">Copy to Clipboard</source>
<context-group purpose="location"><context context-type="linenumber">122</context></context-group>
</trans-unit>
- <trans-unit id="_msg418">
+ <trans-unit id="_msg437">
<source xml:space="preserve">Save…</source>
<context-group purpose="location"><context context-type="linenumber">129</context></context-group>
</trans-unit>
- <trans-unit id="_msg419">
+ <trans-unit id="_msg438">
<source xml:space="preserve">Close</source>
<context-group purpose="location"><context context-type="linenumber">136</context></context-group>
</trans-unit>
@@ -1874,108 +1986,108 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../psbtoperationsdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PSBTOperationsDialog">
- <trans-unit id="_msg420">
+ <trans-unit id="_msg439">
<source xml:space="preserve">Failed to load transaction: %1</source>
<context-group purpose="location"><context context-type="linenumber">61</context></context-group>
</trans-unit>
- <trans-unit id="_msg421">
+ <trans-unit id="_msg440">
<source xml:space="preserve">Failed to sign transaction: %1</source>
<context-group purpose="location"><context context-type="linenumber">86</context></context-group>
</trans-unit>
- <trans-unit id="_msg422">
+ <trans-unit id="_msg441">
<source xml:space="preserve">Cannot sign inputs while wallet is locked.</source>
<context-group purpose="location"><context context-type="linenumber">94</context></context-group>
</trans-unit>
- <trans-unit id="_msg423">
+ <trans-unit id="_msg442">
<source xml:space="preserve">Could not sign any more inputs.</source>
<context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg424">
+ <trans-unit id="_msg443">
<source xml:space="preserve">Signed %1 inputs, but more signatures are still required.</source>
<context-group purpose="location"><context context-type="linenumber">98</context></context-group>
</trans-unit>
- <trans-unit id="_msg425">
+ <trans-unit id="_msg444">
<source xml:space="preserve">Signed transaction successfully. Transaction is ready to broadcast.</source>
<context-group purpose="location"><context context-type="linenumber">101</context></context-group>
</trans-unit>
- <trans-unit id="_msg426">
+ <trans-unit id="_msg445">
<source xml:space="preserve">Unknown error processing transaction.</source>
<context-group purpose="location"><context context-type="linenumber">113</context></context-group>
</trans-unit>
- <trans-unit id="_msg427">
+ <trans-unit id="_msg446">
<source xml:space="preserve">Transaction broadcast successfully! Transaction ID: %1</source>
<context-group purpose="location"><context context-type="linenumber">123</context></context-group>
</trans-unit>
- <trans-unit id="_msg428">
+ <trans-unit id="_msg447">
<source xml:space="preserve">Transaction broadcast failed: %1</source>
<context-group purpose="location"><context context-type="linenumber">126</context></context-group>
</trans-unit>
- <trans-unit id="_msg429">
+ <trans-unit id="_msg448">
<source xml:space="preserve">PSBT copied to clipboard.</source>
<context-group purpose="location"><context context-type="linenumber">135</context></context-group>
</trans-unit>
- <trans-unit id="_msg430">
+ <trans-unit id="_msg449">
<source xml:space="preserve">Save Transaction Data</source>
<context-group purpose="location"><context context-type="linenumber">158</context></context-group>
</trans-unit>
- <trans-unit id="_msg431">
+ <trans-unit id="_msg450">
<source xml:space="preserve">Partially Signed Transaction (Binary)</source>
<context-group purpose="location"><context context-type="linenumber">160</context></context-group>
<note annotates="source" from="developer">Expanded name of the binary PSBT file format. See: BIP 174.</note>
</trans-unit>
- <trans-unit id="_msg432">
+ <trans-unit id="_msg451">
<source xml:space="preserve">PSBT saved to disk.</source>
<context-group purpose="location"><context context-type="linenumber">167</context></context-group>
</trans-unit>
- <trans-unit id="_msg433">
+ <trans-unit id="_msg452">
<source xml:space="preserve"> * Sends %1 to %2</source>
<context-group purpose="location"><context context-type="linenumber">183</context></context-group>
</trans-unit>
- <trans-unit id="_msg434">
+ <trans-unit id="_msg453">
<source xml:space="preserve">Unable to calculate transaction fee or total transaction amount.</source>
<context-group purpose="location"><context context-type="linenumber">193</context></context-group>
</trans-unit>
- <trans-unit id="_msg435">
+ <trans-unit id="_msg454">
<source xml:space="preserve">Pays transaction fee: </source>
<context-group purpose="location"><context context-type="linenumber">195</context></context-group>
</trans-unit>
- <trans-unit id="_msg436">
+ <trans-unit id="_msg455">
<source xml:space="preserve">Total Amount</source>
<context-group purpose="location"><context context-type="linenumber">207</context></context-group>
</trans-unit>
- <trans-unit id="_msg437">
+ <trans-unit id="_msg456">
<source xml:space="preserve">or</source>
<context-group purpose="location"><context context-type="linenumber">210</context></context-group>
</trans-unit>
- <trans-unit id="_msg438">
+ <trans-unit id="_msg457">
<source xml:space="preserve">Transaction has %1 unsigned inputs.</source>
<context-group purpose="location"><context context-type="linenumber">216</context></context-group>
</trans-unit>
- <trans-unit id="_msg439">
+ <trans-unit id="_msg458">
<source xml:space="preserve">Transaction is missing some information about inputs.</source>
<context-group purpose="location"><context context-type="linenumber">262</context></context-group>
</trans-unit>
- <trans-unit id="_msg440">
+ <trans-unit id="_msg459">
<source xml:space="preserve">Transaction still needs signature(s).</source>
<context-group purpose="location"><context context-type="linenumber">266</context></context-group>
</trans-unit>
- <trans-unit id="_msg441">
+ <trans-unit id="_msg460">
<source xml:space="preserve">(But no wallet is loaded.)</source>
<context-group purpose="location"><context context-type="linenumber">269</context></context-group>
</trans-unit>
- <trans-unit id="_msg442">
+ <trans-unit id="_msg461">
<source xml:space="preserve">(But this wallet cannot sign transactions.)</source>
<context-group purpose="location"><context context-type="linenumber">272</context></context-group>
</trans-unit>
- <trans-unit id="_msg443">
+ <trans-unit id="_msg462">
<source xml:space="preserve">(But this wallet does not have the right keys.)</source>
<context-group purpose="location"><context context-type="linenumber">275</context></context-group>
</trans-unit>
- <trans-unit id="_msg444">
+ <trans-unit id="_msg463">
<source xml:space="preserve">Transaction is fully signed and ready for broadcast.</source>
<context-group purpose="location"><context context-type="linenumber">283</context></context-group>
</trans-unit>
- <trans-unit id="_msg445">
+ <trans-unit id="_msg464">
<source xml:space="preserve">Transaction status is unknown.</source>
<context-group purpose="location"><context context-type="linenumber">287</context></context-group>
</trans-unit>
@@ -1983,295 +2095,308 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
</body></file>
<file original="../paymentserver.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PaymentServer">
- <trans-unit id="_msg446">
+ <trans-unit id="_msg465">
<source xml:space="preserve">Payment request error</source>
- <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="_msg447">
+ <trans-unit id="_msg466">
<source xml:space="preserve">Cannot start bitcoin: click-to-pay handler</source>
- <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">153</context></context-group>
</trans-unit>
- <trans-unit id="_msg448">
+ <trans-unit id="_msg467">
<source xml:space="preserve">URI handling</source>
- <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">240</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">217</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">230</context></context-group>
</trans-unit>
- <trans-unit id="_msg449">
+ <trans-unit id="_msg468">
<source xml:space="preserve">&apos;bitcoin://&apos; is not a valid URI. Use &apos;bitcoin:&apos; instead.</source>
- <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
</trans-unit>
- <trans-unit id="_msg450">
+ <trans-unit id="_msg469">
<source xml:space="preserve">Cannot process payment request because BIP70 is not supported.
Due to widespread security flaws in BIP70 it&apos;s strongly recommended that any merchant instructions to switch wallets be ignored.
If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <context-group purpose="location"><context context-type="linenumber">218</context></context-group>
<context-group purpose="location"><context context-type="linenumber">241</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
</trans-unit>
- <trans-unit id="_msg451">
+ <trans-unit id="_msg470">
<source xml:space="preserve">URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">231</context></context-group>
</trans-unit>
- <trans-unit id="_msg452">
+ <trans-unit id="_msg471">
<source xml:space="preserve">Payment request file handling</source>
- <context-group purpose="location"><context context-type="linenumber">263</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../peertablemodel.h" datatype="c" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PeerTableModel">
- <trans-unit id="_msg453">
+ <trans-unit id="_msg472">
<source xml:space="preserve">User Agent</source>
- <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">112</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which contains the peer&apos;s User Agent string.</note>
</trans-unit>
- <trans-unit id="_msg454">
+ <trans-unit id="_msg473">
<source xml:space="preserve">Ping</source>
- <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">103</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which indicates the current latency of the connection with the peer.</note>
</trans-unit>
- <trans-unit id="_msg455">
+ <trans-unit id="_msg474">
<source xml:space="preserve">Peer</source>
- <context-group purpose="location"><context context-type="linenumber">84</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">85</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which contains a unique number used to identify a connection.</note>
</trans-unit>
- <trans-unit id="_msg456">
+ <trans-unit id="_msg475">
+ <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="_msg476">
<source xml:space="preserve">Direction</source>
- <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">94</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which indicates the direction the peer connection was initiated from.</note>
</trans-unit>
- <trans-unit id="_msg457">
+ <trans-unit id="_msg477">
<source xml:space="preserve">Sent</source>
- <context-group purpose="location"><context context-type="linenumber">102</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">106</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</note>
</trans-unit>
- <trans-unit id="_msg458">
+ <trans-unit id="_msg478">
<source xml:space="preserve">Received</source>
- <context-group purpose="location"><context context-type="linenumber">105</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">109</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which indicates the total amount of network information we have received from the peer.</note>
</trans-unit>
- <trans-unit id="_msg459">
+ <trans-unit id="_msg479">
<source xml:space="preserve">Address</source>
- <context-group purpose="location"><context context-type="linenumber">87</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">91</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</note>
</trans-unit>
- <trans-unit id="_msg460">
+ <trans-unit id="_msg480">
<source xml:space="preserve">Type</source>
- <context-group purpose="location"><context context-type="linenumber">93</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">97</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which describes the type of peer connection. The &quot;type&quot; describes why the connection exists.</note>
</trans-unit>
- <trans-unit id="_msg461">
+ <trans-unit id="_msg481">
<source xml:space="preserve">Network</source>
- <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">100</context></context-group>
<note annotates="source" from="developer">Title of Peers Table column which states the network the peer connected through.</note>
</trans-unit>
</group>
</body></file>
<file original="../peertablemodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="PeerTableModel">
- <trans-unit id="_msg462">
+ <trans-unit id="_msg482">
<source xml:space="preserve">Inbound</source>
- <context-group purpose="location"><context context-type="linenumber">79</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">78</context></context-group>
<note annotates="source" from="developer">An Inbound Connection from a Peer.</note>
</trans-unit>
- <trans-unit id="_msg463">
+ <trans-unit id="_msg483">
<source xml:space="preserve">Outbound</source>
- <context-group purpose="location"><context context-type="linenumber">81</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">80</context></context-group>
<note annotates="source" from="developer">An Outbound Connection to a Peer.</note>
</trans-unit>
</group>
</body></file>
<file original="../bitcoinunits.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg464">
+ <trans-unit id="_msg484">
<source xml:space="preserve">Amount</source>
- <context-group purpose="location"><context context-type="linenumber">215</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">197</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../guiutil.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QObject">
- <trans-unit id="_msg465">
+ <trans-unit id="_msg485">
<source xml:space="preserve">Enter a Bitcoin address (e.g. %1)</source>
- <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">129</context></context-group>
</trans-unit>
- <trans-unit id="_msg466">
+ <trans-unit id="_msg486">
+ <source xml:space="preserve">Ctrl+W</source>
+ <context-group purpose="location"><context context-type="linenumber">417</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg487">
<source xml:space="preserve">Unroutable</source>
<context-group purpose="location"><context context-type="linenumber">673</context></context-group>
</trans-unit>
- <trans-unit id="_msg467">
+ <trans-unit id="_msg488">
<source xml:space="preserve">Internal</source>
<context-group purpose="location"><context context-type="linenumber">679</context></context-group>
</trans-unit>
- <trans-unit id="_msg468">
+ <trans-unit id="_msg489">
<source xml:space="preserve">Inbound</source>
<context-group purpose="location"><context context-type="linenumber">692</context></context-group>
<note annotates="source" from="developer">An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</note>
</trans-unit>
- <trans-unit id="_msg469">
+ <trans-unit id="_msg490">
<source xml:space="preserve">Outbound</source>
<context-group purpose="location"><context context-type="linenumber">695</context></context-group>
<note annotates="source" from="developer">An outbound connection to a peer. An outbound connection is a connection initiated by us.</note>
</trans-unit>
- <trans-unit id="_msg470">
+ <trans-unit id="_msg491">
<source xml:space="preserve">Full Relay</source>
<context-group purpose="location"><context context-type="linenumber">700</context></context-group>
<note annotates="source" from="developer">Peer connection type that relays all network information.</note>
</trans-unit>
- <trans-unit id="_msg471">
+ <trans-unit id="_msg492">
<source xml:space="preserve">Block Relay</source>
<context-group purpose="location"><context context-type="linenumber">703</context></context-group>
<note annotates="source" from="developer">Peer connection type that relays network information about blocks and not transactions or addresses.</note>
</trans-unit>
- <trans-unit id="_msg472">
+ <trans-unit id="_msg493">
<source xml:space="preserve">Manual</source>
<context-group purpose="location"><context context-type="linenumber">705</context></context-group>
<note annotates="source" from="developer">Peer connection type established manually through one of several methods.</note>
</trans-unit>
- <trans-unit id="_msg473">
+ <trans-unit id="_msg494">
<source xml:space="preserve">Feeler</source>
<context-group purpose="location"><context context-type="linenumber">707</context></context-group>
<note annotates="source" from="developer">Short-lived peer connection type that tests the aliveness of known addresses.</note>
</trans-unit>
- <trans-unit id="_msg474">
+ <trans-unit id="_msg495">
<source xml:space="preserve">Address Fetch</source>
<context-group purpose="location"><context context-type="linenumber">709</context></context-group>
<note annotates="source" from="developer">Short-lived peer connection type that solicits known addresses from a peer.</note>
</trans-unit>
- <trans-unit id="_msg475">
+ <trans-unit id="_msg496">
<source xml:space="preserve">%1 d</source>
- <context-group purpose="location"><context context-type="linenumber">724</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">722</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">734</context></context-group>
</trans-unit>
- <trans-unit id="_msg476">
+ <trans-unit id="_msg497">
<source xml:space="preserve">%1 h</source>
- <context-group purpose="location"><context context-type="linenumber">726</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">723</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">735</context></context-group>
</trans-unit>
- <trans-unit id="_msg477">
+ <trans-unit id="_msg498">
<source xml:space="preserve">%1 m</source>
- <context-group purpose="location"><context context-type="linenumber">728</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">724</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">736</context></context-group>
</trans-unit>
- <trans-unit id="_msg478">
+ <trans-unit id="_msg499">
<source xml:space="preserve">%1 s</source>
- <context-group purpose="location"><context context-type="linenumber">730</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">758</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">726</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">737</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">763</context></context-group>
</trans-unit>
- <trans-unit id="_msg479">
+ <trans-unit id="_msg500">
<source xml:space="preserve">None</source>
- <context-group purpose="location"><context context-type="linenumber">746</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">751</context></context-group>
</trans-unit>
- <trans-unit id="_msg480">
+ <trans-unit id="_msg501">
<source xml:space="preserve">N/A</source>
- <context-group purpose="location"><context context-type="linenumber">752</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">757</context></context-group>
</trans-unit>
- <trans-unit id="_msg481">
+ <trans-unit id="_msg502">
<source xml:space="preserve">%1 ms</source>
- <context-group purpose="location"><context context-type="linenumber">753</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">758</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">771</context></context-group>
- <trans-unit id="_msg482[0]">
+ <context-group purpose="location"><context context-type="linenumber">776</context></context-group>
+ <trans-unit id="_msg503[0]">
<source xml:space="preserve">%n second(s)</source>
</trans-unit>
- <trans-unit id="_msg482[1]">
+ <trans-unit id="_msg503[1]">
<source xml:space="preserve">%n second(s)</source>
</trans-unit>
</group>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">775</context></context-group>
- <trans-unit id="_msg483[0]">
+ <context-group purpose="location"><context context-type="linenumber">780</context></context-group>
+ <trans-unit id="_msg504[0]">
<source xml:space="preserve">%n minute(s)</source>
</trans-unit>
- <trans-unit id="_msg483[1]">
+ <trans-unit id="_msg504[1]">
<source xml:space="preserve">%n minute(s)</source>
</trans-unit>
</group>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">779</context></context-group>
- <trans-unit id="_msg484[0]">
+ <context-group purpose="location"><context context-type="linenumber">784</context></context-group>
+ <trans-unit id="_msg505[0]">
<source xml:space="preserve">%n hour(s)</source>
</trans-unit>
- <trans-unit id="_msg484[1]">
+ <trans-unit id="_msg505[1]">
<source xml:space="preserve">%n hour(s)</source>
</trans-unit>
</group>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">783</context></context-group>
- <trans-unit id="_msg485[0]">
+ <context-group purpose="location"><context context-type="linenumber">788</context></context-group>
+ <trans-unit id="_msg506[0]">
<source xml:space="preserve">%n day(s)</source>
</trans-unit>
- <trans-unit id="_msg485[1]">
+ <trans-unit id="_msg506[1]">
<source xml:space="preserve">%n day(s)</source>
</trans-unit>
</group>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">787</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">793</context></context-group>
- <trans-unit id="_msg486[0]">
+ <context-group purpose="location"><context context-type="linenumber">792</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">798</context></context-group>
+ <trans-unit id="_msg507[0]">
<source xml:space="preserve">%n week(s)</source>
</trans-unit>
- <trans-unit id="_msg486[1]">
+ <trans-unit id="_msg507[1]">
<source xml:space="preserve">%n week(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg487">
+ <trans-unit id="_msg508">
<source xml:space="preserve">%1 and %2</source>
- <context-group purpose="location"><context context-type="linenumber">793</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">798</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">793</context></context-group>
- <trans-unit id="_msg488[0]">
+ <context-group purpose="location"><context context-type="linenumber">798</context></context-group>
+ <trans-unit id="_msg509[0]">
<source xml:space="preserve">%n year(s)</source>
</trans-unit>
- <trans-unit id="_msg488[1]">
+ <trans-unit id="_msg509[1]">
<source xml:space="preserve">%n year(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg489">
+ <trans-unit id="_msg510">
<source xml:space="preserve">%1 B</source>
- <context-group purpose="location"><context context-type="linenumber">801</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">806</context></context-group>
</trans-unit>
- <trans-unit id="_msg490">
+ <trans-unit id="_msg511">
<source xml:space="preserve">%1 kB</source>
- <context-group purpose="location"><context context-type="linenumber">803</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">808</context></context-group>
</trans-unit>
- <trans-unit id="_msg491">
+ <trans-unit id="_msg512">
<source xml:space="preserve">%1 MB</source>
- <context-group purpose="location"><context context-type="linenumber">805</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">810</context></context-group>
</trans-unit>
- <trans-unit id="_msg492">
+ <trans-unit id="_msg513">
<source xml:space="preserve">%1 GB</source>
- <context-group purpose="location"><context context-type="linenumber">807</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">812</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../qrimagewidget.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="QRImageWidget">
- <trans-unit id="_msg493">
+ <trans-unit id="_msg514">
<source xml:space="preserve">&amp;Save Image…</source>
<context-group purpose="location"><context context-type="linenumber">30</context></context-group>
</trans-unit>
- <trans-unit id="_msg494">
+ <trans-unit id="_msg515">
<source xml:space="preserve">&amp;Copy Image</source>
<context-group purpose="location"><context context-type="linenumber">31</context></context-group>
</trans-unit>
- <trans-unit id="_msg495">
+ <trans-unit id="_msg516">
<source xml:space="preserve">Resulting URI too long, try to reduce the text for label / message.</source>
<context-group purpose="location"><context context-type="linenumber">42</context></context-group>
</trans-unit>
- <trans-unit id="_msg496">
+ <trans-unit id="_msg517">
<source xml:space="preserve">Error encoding URI into QR Code.</source>
<context-group purpose="location"><context context-type="linenumber">49</context></context-group>
</trans-unit>
- <trans-unit id="_msg497">
+ <trans-unit id="_msg518">
<source xml:space="preserve">QR code support not available.</source>
<context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
- <trans-unit id="_msg498">
+ <trans-unit id="_msg519">
<source xml:space="preserve">Save QR Code</source>
<context-group purpose="location"><context context-type="linenumber">120</context></context-group>
</trans-unit>
- <trans-unit id="_msg499">
+ <trans-unit id="_msg520">
<source xml:space="preserve">PNG Image</source>
<context-group purpose="location"><context context-type="linenumber">123</context></context-group>
<note annotates="source" from="developer">Expanded name of the PNG file format. See: https://en.wikipedia.org/wiki/Portable_Network_Graphics.</note>
@@ -2280,7 +2405,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</body></file>
<file original="../forms/debugwindow.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="RPCConsole">
- <trans-unit id="_msg500">
+ <trans-unit id="_msg521">
<source xml:space="preserve">N/A</source>
<context-group purpose="location"><context context-type="linenumber">75</context></context-group>
<context-group purpose="location"><context context-type="linenumber">101</context></context-group>
@@ -2319,290 +2444,293 @@ If you are receiving this error you should request the merchant provide a BIP21
<context-group purpose="location"><context context-type="linenumber">1610</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1636</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1662</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.h</context><context context-type="linenumber">139</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.h</context><context context-type="linenumber">143</context></context-group>
</trans-unit>
- <trans-unit id="_msg501">
+ <trans-unit id="_msg522">
<source xml:space="preserve">Client version</source>
<context-group purpose="location"><context context-type="linenumber">65</context></context-group>
</trans-unit>
- <trans-unit id="_msg502">
+ <trans-unit id="_msg523">
<source xml:space="preserve">&amp;Information</source>
<context-group purpose="location"><context context-type="linenumber">43</context></context-group>
</trans-unit>
- <trans-unit id="_msg503">
+ <trans-unit id="_msg524">
<source xml:space="preserve">General</source>
<context-group purpose="location"><context context-type="linenumber">58</context></context-group>
</trans-unit>
- <trans-unit id="_msg504">
+ <trans-unit id="_msg525">
<source xml:space="preserve">Datadir</source>
<context-group purpose="location"><context context-type="linenumber">114</context></context-group>
</trans-unit>
- <trans-unit id="_msg505">
+ <trans-unit id="_msg526">
<source xml:space="preserve">To specify a non-default location of the data directory use the &apos;%1&apos; option.</source>
<context-group purpose="location"><context context-type="linenumber">124</context></context-group>
</trans-unit>
- <trans-unit id="_msg506">
+ <trans-unit id="_msg527">
<source xml:space="preserve">Blocksdir</source>
<context-group purpose="location"><context context-type="linenumber">143</context></context-group>
</trans-unit>
- <trans-unit id="_msg507">
+ <trans-unit id="_msg528">
<source xml:space="preserve">To specify a non-default location of the blocks directory use the &apos;%1&apos; option.</source>
<context-group purpose="location"><context context-type="linenumber">153</context></context-group>
</trans-unit>
- <trans-unit id="_msg508">
+ <trans-unit id="_msg529">
<source xml:space="preserve">Startup time</source>
<context-group purpose="location"><context context-type="linenumber">172</context></context-group>
</trans-unit>
- <trans-unit id="_msg509">
+ <trans-unit id="_msg530">
<source xml:space="preserve">Network</source>
<context-group purpose="location"><context context-type="linenumber">201</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1093</context></context-group>
</trans-unit>
- <trans-unit id="_msg510">
+ <trans-unit id="_msg531">
<source xml:space="preserve">Name</source>
<context-group purpose="location"><context context-type="linenumber">208</context></context-group>
</trans-unit>
- <trans-unit id="_msg511">
+ <trans-unit id="_msg532">
<source xml:space="preserve">Number of connections</source>
<context-group purpose="location"><context context-type="linenumber">231</context></context-group>
</trans-unit>
- <trans-unit id="_msg512">
+ <trans-unit id="_msg533">
<source xml:space="preserve">Block chain</source>
<context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
- <trans-unit id="_msg513">
+ <trans-unit id="_msg534">
<source xml:space="preserve">Memory Pool</source>
<context-group purpose="location"><context context-type="linenumber">319</context></context-group>
</trans-unit>
- <trans-unit id="_msg514">
+ <trans-unit id="_msg535">
<source xml:space="preserve">Current number of transactions</source>
<context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
- <trans-unit id="_msg515">
+ <trans-unit id="_msg536">
<source xml:space="preserve">Memory usage</source>
<context-group purpose="location"><context context-type="linenumber">349</context></context-group>
</trans-unit>
- <trans-unit id="_msg516">
+ <trans-unit id="_msg537">
<source xml:space="preserve">Wallet: </source>
<context-group purpose="location"><context context-type="linenumber">443</context></context-group>
</trans-unit>
- <trans-unit id="_msg517">
+ <trans-unit id="_msg538">
<source xml:space="preserve">(none)</source>
<context-group purpose="location"><context context-type="linenumber">454</context></context-group>
</trans-unit>
- <trans-unit id="_msg518">
+ <trans-unit id="_msg539">
<source xml:space="preserve">&amp;Reset</source>
<context-group purpose="location"><context context-type="linenumber">665</context></context-group>
</trans-unit>
- <trans-unit id="_msg519">
+ <trans-unit id="_msg540">
<source xml:space="preserve">Received</source>
<context-group purpose="location"><context context-type="linenumber">745</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1453</context></context-group>
</trans-unit>
- <trans-unit id="_msg520">
+ <trans-unit id="_msg541">
<source xml:space="preserve">Sent</source>
<context-group purpose="location"><context context-type="linenumber">825</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1430</context></context-group>
</trans-unit>
- <trans-unit id="_msg521">
+ <trans-unit id="_msg542">
<source xml:space="preserve">&amp;Peers</source>
<context-group purpose="location"><context context-type="linenumber">866</context></context-group>
</trans-unit>
- <trans-unit id="_msg522">
+ <trans-unit id="_msg543">
<source xml:space="preserve">Banned peers</source>
<context-group purpose="location"><context context-type="linenumber">942</context></context-group>
</trans-unit>
- <trans-unit id="_msg523">
+ <trans-unit id="_msg544">
<source xml:space="preserve">Select a peer to view detailed information.</source>
<context-group purpose="location"><context context-type="linenumber">1010</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.cpp</context><context context-type="linenumber">1160</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../rpcconsole.cpp</context><context context-type="linenumber">1155</context></context-group>
</trans-unit>
- <trans-unit id="_msg524">
+ <trans-unit id="_msg545">
<source xml:space="preserve">Version</source>
<context-group purpose="location"><context context-type="linenumber">1116</context></context-group>
</trans-unit>
- <trans-unit id="_msg525">
+ <trans-unit id="_msg546">
<source xml:space="preserve">Starting Block</source>
<context-group purpose="location"><context context-type="linenumber">1240</context></context-group>
</trans-unit>
- <trans-unit id="_msg526">
+ <trans-unit id="_msg547">
<source xml:space="preserve">Synced Headers</source>
<context-group purpose="location"><context context-type="linenumber">1263</context></context-group>
</trans-unit>
- <trans-unit id="_msg527">
+ <trans-unit id="_msg548">
<source xml:space="preserve">Synced Blocks</source>
<context-group purpose="location"><context context-type="linenumber">1286</context></context-group>
</trans-unit>
- <trans-unit id="_msg528">
+ <trans-unit id="_msg549">
<source xml:space="preserve">Last Transaction</source>
<context-group purpose="location"><context context-type="linenumber">1361</context></context-group>
</trans-unit>
- <trans-unit id="_msg529">
+ <trans-unit id="_msg550">
<source xml:space="preserve">The mapped Autonomous System used for diversifying peer selection.</source>
<context-group purpose="location"><context context-type="linenumber">1571</context></context-group>
</trans-unit>
- <trans-unit id="_msg530">
+ <trans-unit id="_msg551">
<source xml:space="preserve">Mapped AS</source>
<context-group purpose="location"><context context-type="linenumber">1574</context></context-group>
</trans-unit>
- <trans-unit id="_msg531">
+ <trans-unit id="_msg552">
<source xml:space="preserve">Whether we relay addresses to this peer.</source>
<context-group purpose="location"><context context-type="linenumber">1597</context></context-group>
- <note annotates="source" from="developer">Tooltip text for the Address Relay field in the peer details area.</note>
+ <note annotates="source" from="developer">Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</note>
</trans-unit>
- <trans-unit id="_msg532">
+ <trans-unit id="_msg553">
<source xml:space="preserve">Address Relay</source>
<context-group purpose="location"><context context-type="linenumber">1600</context></context-group>
+ <note annotates="source" from="developer">Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</note>
</trans-unit>
- <trans-unit id="_msg533">
- <source xml:space="preserve">Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
+ <trans-unit id="_msg554">
+ <source xml:space="preserve">The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
<context-group purpose="location"><context context-type="linenumber">1623</context></context-group>
- <note annotates="source" from="developer">Tooltip text for the Addresses Processed field in the peer details area.</note>
+ <note annotates="source" from="developer">Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</note>
</trans-unit>
- <trans-unit id="_msg534">
+ <trans-unit id="_msg555">
+ <source xml:space="preserve">The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <context-group purpose="location"><context context-type="linenumber">1649</context></context-group>
+ <note annotates="source" from="developer">Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</note>
+ </trans-unit>
+ <trans-unit id="_msg556">
<source xml:space="preserve">Addresses Processed</source>
<context-group purpose="location"><context context-type="linenumber">1626</context></context-group>
+ <note annotates="source" from="developer">Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</note>
</trans-unit>
- <trans-unit id="_msg535">
- <source xml:space="preserve">Total number of addresses dropped due to rate-limiting.</source>
- <context-group purpose="location"><context context-type="linenumber">1649</context></context-group>
- <note annotates="source" from="developer">Tooltip text for the Addresses Rate-Limited field in the peer details area.</note>
- </trans-unit>
- <trans-unit id="_msg536">
+ <trans-unit id="_msg557">
<source xml:space="preserve">Addresses Rate-Limited</source>
<context-group purpose="location"><context context-type="linenumber">1652</context></context-group>
+ <note annotates="source" from="developer">Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</note>
</trans-unit>
- <trans-unit id="_msg537">
+ <trans-unit id="_msg558">
<source xml:space="preserve">User Agent</source>
<context-group purpose="location"><context context-type="linenumber">88</context></context-group>
<context-group purpose="location"><context context-type="linenumber">1139</context></context-group>
</trans-unit>
- <trans-unit id="_msg538">
+ <trans-unit id="_msg559">
<source xml:space="preserve">Node window</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg539">
+ <trans-unit id="_msg560">
<source xml:space="preserve">Current block height</source>
<context-group purpose="location"><context context-type="linenumber">267</context></context-group>
</trans-unit>
- <trans-unit id="_msg540">
+ <trans-unit id="_msg561">
<source xml:space="preserve">Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
<context-group purpose="location"><context context-type="linenumber">397</context></context-group>
</trans-unit>
- <trans-unit id="_msg541">
+ <trans-unit id="_msg562">
<source xml:space="preserve">Decrease font size</source>
<context-group purpose="location"><context context-type="linenumber">475</context></context-group>
</trans-unit>
- <trans-unit id="_msg542">
+ <trans-unit id="_msg563">
<source xml:space="preserve">Increase font size</source>
<context-group purpose="location"><context context-type="linenumber">495</context></context-group>
</trans-unit>
- <trans-unit id="_msg543">
+ <trans-unit id="_msg564">
<source xml:space="preserve">Permissions</source>
<context-group purpose="location"><context context-type="linenumber">1041</context></context-group>
</trans-unit>
- <trans-unit id="_msg544">
+ <trans-unit id="_msg565">
<source xml:space="preserve">The direction and type of peer connection: %1</source>
<context-group purpose="location"><context context-type="linenumber">1064</context></context-group>
</trans-unit>
- <trans-unit id="_msg545">
+ <trans-unit id="_msg566">
<source xml:space="preserve">Direction/Type</source>
<context-group purpose="location"><context context-type="linenumber">1067</context></context-group>
</trans-unit>
- <trans-unit id="_msg546">
+ <trans-unit id="_msg567">
<source xml:space="preserve">The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
<context-group purpose="location"><context context-type="linenumber">1090</context></context-group>
</trans-unit>
- <trans-unit id="_msg547">
+ <trans-unit id="_msg568">
<source xml:space="preserve">Services</source>
<context-group purpose="location"><context context-type="linenumber">1162</context></context-group>
</trans-unit>
- <trans-unit id="_msg548">
+ <trans-unit id="_msg569">
<source xml:space="preserve">Whether the peer requested us to relay transactions.</source>
<context-group purpose="location"><context context-type="linenumber">1188</context></context-group>
</trans-unit>
- <trans-unit id="_msg549">
+ <trans-unit id="_msg570">
<source xml:space="preserve">Wants Tx Relay</source>
<context-group purpose="location"><context context-type="linenumber">1191</context></context-group>
</trans-unit>
- <trans-unit id="_msg550">
+ <trans-unit id="_msg571">
<source xml:space="preserve">High bandwidth BIP152 compact block relay: %1</source>
<context-group purpose="location"><context context-type="linenumber">1214</context></context-group>
</trans-unit>
- <trans-unit id="_msg551">
+ <trans-unit id="_msg572">
<source xml:space="preserve">High Bandwidth</source>
<context-group purpose="location"><context context-type="linenumber">1217</context></context-group>
</trans-unit>
- <trans-unit id="_msg552">
+ <trans-unit id="_msg573">
<source xml:space="preserve">Connection Time</source>
<context-group purpose="location"><context context-type="linenumber">1309</context></context-group>
</trans-unit>
- <trans-unit id="_msg553">
+ <trans-unit id="_msg574">
<source xml:space="preserve">Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
<context-group purpose="location"><context context-type="linenumber">1332</context></context-group>
</trans-unit>
- <trans-unit id="_msg554">
+ <trans-unit id="_msg575">
<source xml:space="preserve">Last Block</source>
<context-group purpose="location"><context context-type="linenumber">1335</context></context-group>
</trans-unit>
- <trans-unit id="_msg555">
+ <trans-unit id="_msg576">
<source xml:space="preserve">Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
<context-group purpose="location"><context context-type="linenumber">1358</context></context-group>
<note annotates="source" from="developer">Tooltip text for the Last Transaction field in the peer details area.</note>
</trans-unit>
- <trans-unit id="_msg556">
+ <trans-unit id="_msg577">
<source xml:space="preserve">Last Send</source>
<context-group purpose="location"><context context-type="linenumber">1384</context></context-group>
</trans-unit>
- <trans-unit id="_msg557">
+ <trans-unit id="_msg578">
<source xml:space="preserve">Last Receive</source>
<context-group purpose="location"><context context-type="linenumber">1407</context></context-group>
</trans-unit>
- <trans-unit id="_msg558">
+ <trans-unit id="_msg579">
<source xml:space="preserve">Ping Time</source>
<context-group purpose="location"><context context-type="linenumber">1476</context></context-group>
</trans-unit>
- <trans-unit id="_msg559">
+ <trans-unit id="_msg580">
<source xml:space="preserve">The duration of a currently outstanding ping.</source>
<context-group purpose="location"><context context-type="linenumber">1499</context></context-group>
</trans-unit>
- <trans-unit id="_msg560">
+ <trans-unit id="_msg581">
<source xml:space="preserve">Ping Wait</source>
<context-group purpose="location"><context context-type="linenumber">1502</context></context-group>
</trans-unit>
- <trans-unit id="_msg561">
+ <trans-unit id="_msg582">
<source xml:space="preserve">Min Ping</source>
<context-group purpose="location"><context context-type="linenumber">1525</context></context-group>
</trans-unit>
- <trans-unit id="_msg562">
+ <trans-unit id="_msg583">
<source xml:space="preserve">Time Offset</source>
<context-group purpose="location"><context context-type="linenumber">1548</context></context-group>
</trans-unit>
- <trans-unit id="_msg563">
+ <trans-unit id="_msg584">
<source xml:space="preserve">Last block time</source>
<context-group purpose="location"><context context-type="linenumber">290</context></context-group>
</trans-unit>
- <trans-unit id="_msg564">
+ <trans-unit id="_msg585">
<source xml:space="preserve">&amp;Open</source>
<context-group purpose="location"><context context-type="linenumber">400</context></context-group>
</trans-unit>
- <trans-unit id="_msg565">
+ <trans-unit id="_msg586">
<source xml:space="preserve">&amp;Console</source>
<context-group purpose="location"><context context-type="linenumber">426</context></context-group>
</trans-unit>
- <trans-unit id="_msg566">
+ <trans-unit id="_msg587">
<source xml:space="preserve">&amp;Network Traffic</source>
<context-group purpose="location"><context context-type="linenumber">613</context></context-group>
</trans-unit>
- <trans-unit id="_msg567">
+ <trans-unit id="_msg588">
<source xml:space="preserve">Totals</source>
<context-group purpose="location"><context context-type="linenumber">681</context></context-group>
</trans-unit>
- <trans-unit id="_msg568">
+ <trans-unit id="_msg589">
<source xml:space="preserve">Debug log file</source>
<context-group purpose="location"><context context-type="linenumber">390</context></context-group>
</trans-unit>
- <trans-unit id="_msg569">
+ <trans-unit id="_msg590">
<source xml:space="preserve">Clear console</source>
<context-group purpose="location"><context context-type="linenumber">515</context></context-group>
</trans-unit>
@@ -2610,123 +2738,139 @@ If you are receiving this error you should request the merchant provide a BIP21
</body></file>
<file original="../rpcconsole.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="RPCConsole">
- <trans-unit id="_msg570">
+ <trans-unit id="_msg591">
<source xml:space="preserve">In:</source>
- <context-group purpose="location"><context context-type="linenumber">959</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">953</context></context-group>
</trans-unit>
- <trans-unit id="_msg571">
+ <trans-unit id="_msg592">
<source xml:space="preserve">Out:</source>
- <context-group purpose="location"><context context-type="linenumber">960</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">954</context></context-group>
</trans-unit>
- <trans-unit id="_msg572">
+ <trans-unit id="_msg593">
<source xml:space="preserve">Inbound: initiated by peer</source>
- <context-group purpose="location"><context context-type="linenumber">503</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">496</context></context-group>
<note annotates="source" from="developer">Explanatory text for an inbound peer connection.</note>
</trans-unit>
- <trans-unit id="_msg573">
+ <trans-unit id="_msg594">
<source xml:space="preserve">Outbound Full Relay: default</source>
- <context-group purpose="location"><context context-type="linenumber">507</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">500</context></context-group>
<note annotates="source" from="developer">Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</note>
</trans-unit>
- <trans-unit id="_msg574">
+ <trans-unit id="_msg595">
<source xml:space="preserve">Outbound Block Relay: does not relay transactions or addresses</source>
- <context-group purpose="location"><context context-type="linenumber">510</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">503</context></context-group>
<note annotates="source" from="developer">Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</note>
</trans-unit>
- <trans-unit id="_msg575">
+ <trans-unit id="_msg596">
<source xml:space="preserve">Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
- <context-group purpose="location"><context context-type="linenumber">515</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">508</context></context-group>
<note annotates="source" from="developer">Explanatory text for an outbound peer connection that was established manually through one of several methods. The numbered arguments are stand-ins for the methods available to establish manual connections.</note>
</trans-unit>
- <trans-unit id="_msg576">
+ <trans-unit id="_msg597">
<source xml:space="preserve">Outbound Feeler: short-lived, for testing addresses</source>
- <context-group purpose="location"><context context-type="linenumber">521</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">514</context></context-group>
<note annotates="source" from="developer">Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</note>
</trans-unit>
- <trans-unit id="_msg577">
+ <trans-unit id="_msg598">
<source xml:space="preserve">Outbound Address Fetch: short-lived, for soliciting addresses</source>
- <context-group purpose="location"><context context-type="linenumber">524</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">517</context></context-group>
<note annotates="source" from="developer">Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</note>
</trans-unit>
- <trans-unit id="_msg578">
+ <trans-unit id="_msg599">
<source xml:space="preserve">we selected the peer for high bandwidth relay</source>
- <context-group purpose="location"><context context-type="linenumber">528</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">521</context></context-group>
</trans-unit>
- <trans-unit id="_msg579">
+ <trans-unit id="_msg600">
<source xml:space="preserve">the peer selected us for high bandwidth relay</source>
- <context-group purpose="location"><context context-type="linenumber">529</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">522</context></context-group>
</trans-unit>
- <trans-unit id="_msg580">
+ <trans-unit id="_msg601">
<source xml:space="preserve">no high bandwidth relay selected</source>
- <context-group purpose="location"><context context-type="linenumber">530</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">523</context></context-group>
</trans-unit>
- <trans-unit id="_msg581">
+ <trans-unit id="_msg602">
<source xml:space="preserve">Ctrl++</source>
- <context-group purpose="location"><context context-type="linenumber">543</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">536</context></context-group>
<note annotates="source" from="developer">Main shortcut to increase the RPC console font size.</note>
</trans-unit>
- <trans-unit id="_msg582">
+ <trans-unit id="_msg603">
<source xml:space="preserve">Ctrl+=</source>
- <context-group purpose="location"><context context-type="linenumber">545</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">538</context></context-group>
<note annotates="source" from="developer">Secondary shortcut to increase the RPC console font size.</note>
</trans-unit>
- <trans-unit id="_msg583">
+ <trans-unit id="_msg604">
<source xml:space="preserve">Ctrl+-</source>
- <context-group purpose="location"><context context-type="linenumber">549</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">542</context></context-group>
<note annotates="source" from="developer">Main shortcut to decrease the RPC console font size.</note>
</trans-unit>
- <trans-unit id="_msg584">
+ <trans-unit id="_msg605">
<source xml:space="preserve">Ctrl+_</source>
- <context-group purpose="location"><context context-type="linenumber">551</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">544</context></context-group>
<note annotates="source" from="developer">Secondary shortcut to decrease the RPC console font size.</note>
</trans-unit>
- <trans-unit id="_msg585">
+ <trans-unit id="_msg606">
<source xml:space="preserve">&amp;Copy address</source>
- <context-group purpose="location"><context context-type="linenumber">702</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">695</context></context-group>
<note annotates="source" from="developer">Context menu action to copy the address of a peer.</note>
</trans-unit>
- <trans-unit id="_msg586">
+ <trans-unit id="_msg607">
<source xml:space="preserve">&amp;Disconnect</source>
- <context-group purpose="location"><context context-type="linenumber">706</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">699</context></context-group>
</trans-unit>
- <trans-unit id="_msg587">
+ <trans-unit id="_msg608">
<source xml:space="preserve">1 &amp;hour</source>
- <context-group purpose="location"><context context-type="linenumber">707</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">700</context></context-group>
</trans-unit>
- <trans-unit id="_msg588">
+ <trans-unit id="_msg609">
<source xml:space="preserve">1 d&amp;ay</source>
- <context-group purpose="location"><context context-type="linenumber">708</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">701</context></context-group>
</trans-unit>
- <trans-unit id="_msg589">
+ <trans-unit id="_msg610">
<source xml:space="preserve">1 &amp;week</source>
- <context-group purpose="location"><context context-type="linenumber">709</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">702</context></context-group>
</trans-unit>
- <trans-unit id="_msg590">
+ <trans-unit id="_msg611">
<source xml:space="preserve">1 &amp;year</source>
- <context-group purpose="location"><context context-type="linenumber">710</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">703</context></context-group>
</trans-unit>
- <trans-unit id="_msg591">
+ <trans-unit id="_msg612">
<source xml:space="preserve">&amp;Copy IP/Netmask</source>
- <context-group purpose="location"><context context-type="linenumber">735</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">729</context></context-group>
<note annotates="source" from="developer">Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer&apos;s IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</note>
</trans-unit>
- <trans-unit id="_msg592">
+ <trans-unit id="_msg613">
<source xml:space="preserve">&amp;Unban</source>
- <context-group purpose="location"><context context-type="linenumber">739</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">733</context></context-group>
</trans-unit>
- <trans-unit id="_msg593">
+ <trans-unit id="_msg614">
<source xml:space="preserve">Network activity disabled</source>
- <context-group purpose="location"><context context-type="linenumber">963</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">957</context></context-group>
</trans-unit>
- <trans-unit id="_msg594">
+ <trans-unit id="_msg615">
<source xml:space="preserve">Executing command without any wallet</source>
- <context-group purpose="location"><context context-type="linenumber">1040</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1035</context></context-group>
</trans-unit>
- <trans-unit id="_msg595">
+ <trans-unit id="_msg616">
+ <source xml:space="preserve">Ctrl+I</source>
+ <context-group purpose="location"><context context-type="linenumber">1351</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg617">
+ <source xml:space="preserve">Ctrl+T</source>
+ <context-group purpose="location"><context context-type="linenumber">1352</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg618">
+ <source xml:space="preserve">Ctrl+N</source>
+ <context-group purpose="location"><context context-type="linenumber">1353</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg619">
+ <source xml:space="preserve">Ctrl+P</source>
+ <context-group purpose="location"><context context-type="linenumber">1354</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg620">
<source xml:space="preserve">Executing command using &quot;%1&quot; wallet</source>
- <context-group purpose="location"><context context-type="linenumber">1038</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1033</context></context-group>
</trans-unit>
- <trans-unit id="_msg596">
+ <trans-unit id="_msg621">
<source xml:space="preserve">Welcome to the %1 RPC console.
Use up and down arrows to navigate history, and %2 to clear screen.
Use %3 and %4 to increase or decrease the font size.
@@ -2734,124 +2878,124 @@ Type %5 for an overview of available commands.
For more information on using this console, type %6.
%7WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.%8</source>
- <context-group purpose="location"><context context-type="linenumber">893</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">887</context></context-group>
<note annotates="source" from="developer">RPC console welcome message. Placeholders %7 and %8 are style tags for the warning content, and they are not space separated from the rest of the text intentionally.</note>
</trans-unit>
- <trans-unit id="_msg597">
+ <trans-unit id="_msg622">
<source xml:space="preserve">Executing…</source>
- <context-group purpose="location"><context context-type="linenumber">1048</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1043</context></context-group>
<note annotates="source" from="developer">A console message indicating an entered command is currently being executed.</note>
</trans-unit>
- <trans-unit id="_msg598">
+ <trans-unit id="_msg623">
<source xml:space="preserve">(peer: %1)</source>
- <context-group purpose="location"><context context-type="linenumber">1166</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1161</context></context-group>
</trans-unit>
- <trans-unit id="_msg599">
+ <trans-unit id="_msg624">
<source xml:space="preserve">via %1</source>
- <context-group purpose="location"><context context-type="linenumber">1168</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1163</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../rpcconsole.h" datatype="c" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="RPCConsole">
- <trans-unit id="_msg600">
+ <trans-unit id="_msg625">
<source xml:space="preserve">Yes</source>
- <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg601">
+ <trans-unit id="_msg626">
<source xml:space="preserve">No</source>
- <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg602">
+ <trans-unit id="_msg627">
<source xml:space="preserve">To</source>
- <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg603">
+ <trans-unit id="_msg628">
<source xml:space="preserve">From</source>
- <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
</trans-unit>
- <trans-unit id="_msg604">
+ <trans-unit id="_msg629">
<source xml:space="preserve">Ban for</source>
- <context-group purpose="location"><context context-type="linenumber">139</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">143</context></context-group>
</trans-unit>
- <trans-unit id="_msg605">
+ <trans-unit id="_msg630">
<source xml:space="preserve">Never</source>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">185</context></context-group>
</trans-unit>
- <trans-unit id="_msg606">
+ <trans-unit id="_msg631">
<source xml:space="preserve">Unknown</source>
- <context-group purpose="location"><context context-type="linenumber">139</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">143</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/receivecoinsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="ReceiveCoinsDialog">
- <trans-unit id="_msg607">
+ <trans-unit id="_msg632">
<source xml:space="preserve">&amp;Amount:</source>
<context-group purpose="location"><context context-type="linenumber">37</context></context-group>
</trans-unit>
- <trans-unit id="_msg608">
+ <trans-unit id="_msg633">
<source xml:space="preserve">&amp;Label:</source>
<context-group purpose="location"><context context-type="linenumber">83</context></context-group>
</trans-unit>
- <trans-unit id="_msg609">
+ <trans-unit id="_msg634">
<source xml:space="preserve">&amp;Message:</source>
<context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg610">
+ <trans-unit id="_msg635">
<source xml:space="preserve">An optional message to attach to the payment request, which will be displayed when the request is opened. Note: The message will not be sent with the payment over the Bitcoin network.</source>
<context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg611">
+ <trans-unit id="_msg636">
<source xml:space="preserve">An optional label to associate with the new receiving address.</source>
<context-group purpose="location"><context context-type="linenumber">80</context></context-group>
</trans-unit>
- <trans-unit id="_msg612">
+ <trans-unit id="_msg637">
<source xml:space="preserve">Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
</trans-unit>
- <trans-unit id="_msg613">
+ <trans-unit id="_msg638">
<source xml:space="preserve">An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
<context-group purpose="location"><context context-type="linenumber">34</context></context-group>
<context-group purpose="location"><context context-type="linenumber">193</context></context-group>
</trans-unit>
- <trans-unit id="_msg614">
+ <trans-unit id="_msg639">
<source xml:space="preserve">An optional label to associate with the new receiving address (used by you to identify an invoice). It is also attached to the payment request.</source>
<context-group purpose="location"><context context-type="linenumber">66</context></context-group>
</trans-unit>
- <trans-unit id="_msg615">
+ <trans-unit id="_msg640">
<source xml:space="preserve">An optional message that is attached to the payment request and may be displayed to the sender.</source>
<context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg616">
+ <trans-unit id="_msg641">
<source xml:space="preserve">&amp;Create new receiving address</source>
<context-group purpose="location"><context context-type="linenumber">111</context></context-group>
</trans-unit>
- <trans-unit id="_msg617">
+ <trans-unit id="_msg642">
<source xml:space="preserve">Clear all fields of the form.</source>
<context-group purpose="location"><context context-type="linenumber">134</context></context-group>
</trans-unit>
- <trans-unit id="_msg618">
+ <trans-unit id="_msg643">
<source xml:space="preserve">Clear</source>
<context-group purpose="location"><context context-type="linenumber">137</context></context-group>
</trans-unit>
- <trans-unit id="_msg619">
+ <trans-unit id="_msg644">
<source xml:space="preserve">Requested payments history</source>
<context-group purpose="location"><context context-type="linenumber">273</context></context-group>
</trans-unit>
- <trans-unit id="_msg620">
+ <trans-unit id="_msg645">
<source xml:space="preserve">Show the selected request (does the same as double clicking an entry)</source>
<context-group purpose="location"><context context-type="linenumber">298</context></context-group>
</trans-unit>
- <trans-unit id="_msg621">
+ <trans-unit id="_msg646">
<source xml:space="preserve">Show</source>
<context-group purpose="location"><context context-type="linenumber">301</context></context-group>
</trans-unit>
- <trans-unit id="_msg622">
+ <trans-unit id="_msg647">
<source xml:space="preserve">Remove the selected entries from the list</source>
<context-group purpose="location"><context context-type="linenumber">318</context></context-group>
</trans-unit>
- <trans-unit id="_msg623">
+ <trans-unit id="_msg648">
<source xml:space="preserve">Remove</source>
<context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
@@ -2859,31 +3003,31 @@ For more information on using this console, type %6.
</body></file>
<file original="../receivecoinsdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="ReceiveCoinsDialog">
- <trans-unit id="_msg624">
+ <trans-unit id="_msg649">
<source xml:space="preserve">Copy &amp;URI</source>
<context-group purpose="location"><context context-type="linenumber">47</context></context-group>
</trans-unit>
- <trans-unit id="_msg625">
+ <trans-unit id="_msg650">
<source xml:space="preserve">&amp;Copy address</source>
<context-group purpose="location"><context context-type="linenumber">48</context></context-group>
</trans-unit>
- <trans-unit id="_msg626">
+ <trans-unit id="_msg651">
<source xml:space="preserve">Copy &amp;label</source>
<context-group purpose="location"><context context-type="linenumber">49</context></context-group>
</trans-unit>
- <trans-unit id="_msg627">
+ <trans-unit id="_msg652">
<source xml:space="preserve">Copy &amp;message</source>
<context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg628">
+ <trans-unit id="_msg653">
<source xml:space="preserve">Copy &amp;amount</source>
<context-group purpose="location"><context context-type="linenumber">51</context></context-group>
</trans-unit>
- <trans-unit id="_msg629">
+ <trans-unit id="_msg654">
<source xml:space="preserve">Could not unlock wallet.</source>
<context-group purpose="location"><context context-type="linenumber">176</context></context-group>
</trans-unit>
- <trans-unit id="_msg630">
+ <trans-unit id="_msg655">
<source xml:space="preserve">Could not generate new %1 address</source>
<context-group purpose="location"><context context-type="linenumber">181</context></context-group>
</trans-unit>
@@ -2891,51 +3035,51 @@ For more information on using this console, type %6.
</body></file>
<file original="../forms/receiverequestdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="ReceiveRequestDialog">
- <trans-unit id="_msg631">
+ <trans-unit id="_msg656">
<source xml:space="preserve">Request payment to …</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg632">
+ <trans-unit id="_msg657">
<source xml:space="preserve">Address:</source>
<context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
- <trans-unit id="_msg633">
+ <trans-unit id="_msg658">
<source xml:space="preserve">Amount:</source>
<context-group purpose="location"><context context-type="linenumber">119</context></context-group>
</trans-unit>
- <trans-unit id="_msg634">
+ <trans-unit id="_msg659">
<source xml:space="preserve">Label:</source>
<context-group purpose="location"><context context-type="linenumber">148</context></context-group>
</trans-unit>
- <trans-unit id="_msg635">
+ <trans-unit id="_msg660">
<source xml:space="preserve">Message:</source>
<context-group purpose="location"><context context-type="linenumber">180</context></context-group>
</trans-unit>
- <trans-unit id="_msg636">
+ <trans-unit id="_msg661">
<source xml:space="preserve">Wallet:</source>
<context-group purpose="location"><context context-type="linenumber">212</context></context-group>
</trans-unit>
- <trans-unit id="_msg637">
+ <trans-unit id="_msg662">
<source xml:space="preserve">Copy &amp;URI</source>
<context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
- <trans-unit id="_msg638">
+ <trans-unit id="_msg663">
<source xml:space="preserve">Copy &amp;Address</source>
<context-group purpose="location"><context context-type="linenumber">250</context></context-group>
</trans-unit>
- <trans-unit id="_msg639">
+ <trans-unit id="_msg664">
<source xml:space="preserve">&amp;Verify</source>
<context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
- <trans-unit id="_msg640">
+ <trans-unit id="_msg665">
<source xml:space="preserve">Verify this address on e.g. a hardware wallet screen</source>
<context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
- <trans-unit id="_msg641">
+ <trans-unit id="_msg666">
<source xml:space="preserve">&amp;Save Image…</source>
<context-group purpose="location"><context context-type="linenumber">273</context></context-group>
</trans-unit>
- <trans-unit id="_msg642">
+ <trans-unit id="_msg667">
<source xml:space="preserve">Payment information</source>
<context-group purpose="location"><context context-type="linenumber">39</context></context-group>
</trans-unit>
@@ -2943,7 +3087,7 @@ For more information on using this console, type %6.
</body></file>
<file original="../receiverequestdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="ReceiveRequestDialog">
- <trans-unit id="_msg643">
+ <trans-unit id="_msg668">
<source xml:space="preserve">Request payment to %1</source>
<context-group purpose="location"><context context-type="linenumber">49</context></context-group>
</trans-unit>
@@ -2951,186 +3095,186 @@ For more information on using this console, type %6.
</body></file>
<file original="../recentrequeststablemodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="RecentRequestsTableModel">
- <trans-unit id="_msg644">
+ <trans-unit id="_msg669">
<source xml:space="preserve">Date</source>
<context-group purpose="location"><context context-type="linenumber">32</context></context-group>
</trans-unit>
- <trans-unit id="_msg645">
+ <trans-unit id="_msg670">
<source xml:space="preserve">Label</source>
<context-group purpose="location"><context context-type="linenumber">32</context></context-group>
</trans-unit>
- <trans-unit id="_msg646">
+ <trans-unit id="_msg671">
<source xml:space="preserve">Message</source>
<context-group purpose="location"><context context-type="linenumber">32</context></context-group>
</trans-unit>
- <trans-unit id="_msg647">
+ <trans-unit id="_msg672">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">73</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">70</context></context-group>
</trans-unit>
- <trans-unit id="_msg648">
+ <trans-unit id="_msg673">
<source xml:space="preserve">(no message)</source>
- <context-group purpose="location"><context context-type="linenumber">82</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">79</context></context-group>
</trans-unit>
- <trans-unit id="_msg649">
+ <trans-unit id="_msg674">
<source xml:space="preserve">(no amount requested)</source>
- <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">87</context></context-group>
</trans-unit>
- <trans-unit id="_msg650">
+ <trans-unit id="_msg675">
<source xml:space="preserve">Requested</source>
- <context-group purpose="location"><context context-type="linenumber">133</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">130</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/sendcoinsdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendCoinsDialog">
- <trans-unit id="_msg651">
+ <trans-unit id="_msg676">
<source xml:space="preserve">Send Coins</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
- <context-group purpose="location"><context context-type="sourcefile">../sendcoinsdialog.cpp</context><context context-type="linenumber">752</context></context-group>
+ <context-group purpose="location"><context context-type="sourcefile">../sendcoinsdialog.cpp</context><context context-type="linenumber">757</context></context-group>
</trans-unit>
- <trans-unit id="_msg652">
+ <trans-unit id="_msg677">
<source xml:space="preserve">Coin Control Features</source>
<context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
- <trans-unit id="_msg653">
+ <trans-unit id="_msg678">
<source xml:space="preserve">automatically selected</source>
<context-group purpose="location"><context context-type="linenumber">120</context></context-group>
</trans-unit>
- <trans-unit id="_msg654">
+ <trans-unit id="_msg679">
<source xml:space="preserve">Insufficient funds!</source>
<context-group purpose="location"><context context-type="linenumber">139</context></context-group>
</trans-unit>
- <trans-unit id="_msg655">
+ <trans-unit id="_msg680">
<source xml:space="preserve">Quantity:</source>
<context-group purpose="location"><context context-type="linenumber">228</context></context-group>
</trans-unit>
- <trans-unit id="_msg656">
+ <trans-unit id="_msg681">
<source xml:space="preserve">Bytes:</source>
<context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
- <trans-unit id="_msg657">
+ <trans-unit id="_msg682">
<source xml:space="preserve">Amount:</source>
<context-group purpose="location"><context context-type="linenumber">311</context></context-group>
</trans-unit>
- <trans-unit id="_msg658">
+ <trans-unit id="_msg683">
<source xml:space="preserve">Fee:</source>
<context-group purpose="location"><context context-type="linenumber">391</context></context-group>
</trans-unit>
- <trans-unit id="_msg659">
+ <trans-unit id="_msg684">
<source xml:space="preserve">After Fee:</source>
<context-group purpose="location"><context context-type="linenumber">442</context></context-group>
</trans-unit>
- <trans-unit id="_msg660">
+ <trans-unit id="_msg685">
<source xml:space="preserve">Change:</source>
<context-group purpose="location"><context context-type="linenumber">474</context></context-group>
</trans-unit>
- <trans-unit id="_msg661">
+ <trans-unit id="_msg686">
<source xml:space="preserve">If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
<context-group purpose="location"><context context-type="linenumber">518</context></context-group>
</trans-unit>
- <trans-unit id="_msg662">
+ <trans-unit id="_msg687">
<source xml:space="preserve">Custom change address</source>
<context-group purpose="location"><context context-type="linenumber">521</context></context-group>
</trans-unit>
- <trans-unit id="_msg663">
+ <trans-unit id="_msg688">
<source xml:space="preserve">Transaction Fee:</source>
<context-group purpose="location"><context context-type="linenumber">727</context></context-group>
</trans-unit>
- <trans-unit id="_msg664">
+ <trans-unit id="_msg689">
<source xml:space="preserve">Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until you have validated the complete chain.</source>
<context-group purpose="location"><context context-type="linenumber">765</context></context-group>
</trans-unit>
- <trans-unit id="_msg665">
+ <trans-unit id="_msg690">
<source xml:space="preserve">Warning: Fee estimation is currently not possible.</source>
<context-group purpose="location"><context context-type="linenumber">774</context></context-group>
</trans-unit>
- <trans-unit id="_msg666">
+ <trans-unit id="_msg691">
<source xml:space="preserve">per kilobyte</source>
<context-group purpose="location"><context context-type="linenumber">856</context></context-group>
</trans-unit>
- <trans-unit id="_msg667">
+ <trans-unit id="_msg692">
<source xml:space="preserve">Hide</source>
<context-group purpose="location"><context context-type="linenumber">803</context></context-group>
</trans-unit>
- <trans-unit id="_msg668">
+ <trans-unit id="_msg693">
<source xml:space="preserve">Recommended:</source>
<context-group purpose="location"><context context-type="linenumber">915</context></context-group>
</trans-unit>
- <trans-unit id="_msg669">
+ <trans-unit id="_msg694">
<source xml:space="preserve">Custom:</source>
<context-group purpose="location"><context context-type="linenumber">945</context></context-group>
</trans-unit>
- <trans-unit id="_msg670">
+ <trans-unit id="_msg695">
<source xml:space="preserve">Send to multiple recipients at once</source>
<context-group purpose="location"><context context-type="linenumber">1160</context></context-group>
</trans-unit>
- <trans-unit id="_msg671">
+ <trans-unit id="_msg696">
<source xml:space="preserve">Add &amp;Recipient</source>
<context-group purpose="location"><context context-type="linenumber">1163</context></context-group>
</trans-unit>
- <trans-unit id="_msg672">
+ <trans-unit id="_msg697">
<source xml:space="preserve">Clear all fields of the form.</source>
<context-group purpose="location"><context context-type="linenumber">1143</context></context-group>
</trans-unit>
- <trans-unit id="_msg673">
+ <trans-unit id="_msg698">
<source xml:space="preserve">Inputs…</source>
<context-group purpose="location"><context context-type="linenumber">110</context></context-group>
</trans-unit>
- <trans-unit id="_msg674">
+ <trans-unit id="_msg699">
<source xml:space="preserve">Dust:</source>
<context-group purpose="location"><context context-type="linenumber">343</context></context-group>
</trans-unit>
- <trans-unit id="_msg675">
+ <trans-unit id="_msg700">
<source xml:space="preserve">Choose…</source>
<context-group purpose="location"><context context-type="linenumber">741</context></context-group>
</trans-unit>
- <trans-unit id="_msg676">
+ <trans-unit id="_msg701">
<source xml:space="preserve">Hide transaction fee settings</source>
<context-group purpose="location"><context context-type="linenumber">800</context></context-group>
</trans-unit>
- <trans-unit id="_msg677">
+ <trans-unit id="_msg702">
<source xml:space="preserve">Specify a custom fee per kB (1,000 bytes) of the transaction&apos;s virtual size.
Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100 satoshis per kvB&quot; for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
<context-group purpose="location"><context context-type="linenumber">851</context></context-group>
</trans-unit>
- <trans-unit id="_msg678">
+ <trans-unit id="_msg703">
<source xml:space="preserve">When there is less transaction volume than space in the blocks, miners as well as relaying nodes may enforce a minimum fee. Paying only this minimum fee is just fine, but be aware that this can result in a never confirming transaction once there is more demand for bitcoin transactions than the network can process.</source>
<context-group purpose="location"><context context-type="linenumber">886</context></context-group>
</trans-unit>
- <trans-unit id="_msg679">
+ <trans-unit id="_msg704">
<source xml:space="preserve">A too low fee might result in a never confirming transaction (read the tooltip)</source>
<context-group purpose="location"><context context-type="linenumber">889</context></context-group>
</trans-unit>
- <trans-unit id="_msg680">
+ <trans-unit id="_msg705">
<source xml:space="preserve">(Smart fee not initialized yet. This usually takes a few blocks…)</source>
<context-group purpose="location"><context context-type="linenumber">994</context></context-group>
</trans-unit>
- <trans-unit id="_msg681">
+ <trans-unit id="_msg706">
<source xml:space="preserve">Confirmation time target:</source>
<context-group purpose="location"><context context-type="linenumber">1020</context></context-group>
</trans-unit>
- <trans-unit id="_msg682">
+ <trans-unit id="_msg707">
<source xml:space="preserve">Enable Replace-By-Fee</source>
<context-group purpose="location"><context context-type="linenumber">1078</context></context-group>
</trans-unit>
- <trans-unit id="_msg683">
+ <trans-unit id="_msg708">
<source xml:space="preserve">With Replace-By-Fee (BIP-125) you can increase a transaction&apos;s fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
<context-group purpose="location"><context context-type="linenumber">1081</context></context-group>
</trans-unit>
- <trans-unit id="_msg684">
+ <trans-unit id="_msg709">
<source xml:space="preserve">Clear &amp;All</source>
<context-group purpose="location"><context context-type="linenumber">1146</context></context-group>
</trans-unit>
- <trans-unit id="_msg685">
+ <trans-unit id="_msg710">
<source xml:space="preserve">Balance:</source>
<context-group purpose="location"><context context-type="linenumber">1201</context></context-group>
</trans-unit>
- <trans-unit id="_msg686">
+ <trans-unit id="_msg711">
<source xml:space="preserve">Confirm the send action</source>
<context-group purpose="location"><context context-type="linenumber">1117</context></context-group>
</trans-unit>
- <trans-unit id="_msg687">
+ <trans-unit id="_msg712">
<source xml:space="preserve">S&amp;end</source>
<context-group purpose="location"><context context-type="linenumber">1120</context></context-group>
</trans-unit>
@@ -3138,422 +3282,396 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../sendcoinsdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendCoinsDialog">
- <trans-unit id="_msg688">
+ <trans-unit id="_msg713">
<source xml:space="preserve">Copy quantity</source>
<context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg689">
+ <trans-unit id="_msg714">
<source xml:space="preserve">Copy amount</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
</trans-unit>
- <trans-unit id="_msg690">
+ <trans-unit id="_msg715">
<source xml:space="preserve">Copy fee</source>
<context-group purpose="location"><context context-type="linenumber">101</context></context-group>
</trans-unit>
- <trans-unit id="_msg691">
+ <trans-unit id="_msg716">
<source xml:space="preserve">Copy after fee</source>
<context-group purpose="location"><context context-type="linenumber">102</context></context-group>
</trans-unit>
- <trans-unit id="_msg692">
+ <trans-unit id="_msg717">
<source xml:space="preserve">Copy bytes</source>
<context-group purpose="location"><context context-type="linenumber">103</context></context-group>
</trans-unit>
- <trans-unit id="_msg693">
+ <trans-unit id="_msg718">
<source xml:space="preserve">Copy dust</source>
<context-group purpose="location"><context context-type="linenumber">104</context></context-group>
</trans-unit>
- <trans-unit id="_msg694">
+ <trans-unit id="_msg719">
<source xml:space="preserve">Copy change</source>
<context-group purpose="location"><context context-type="linenumber">105</context></context-group>
</trans-unit>
- <trans-unit id="_msg695">
+ <trans-unit id="_msg720">
<source xml:space="preserve">%1 (%2 blocks)</source>
- <context-group purpose="location"><context context-type="linenumber">181</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">179</context></context-group>
</trans-unit>
- <trans-unit id="_msg696">
+ <trans-unit id="_msg721">
<source xml:space="preserve">Sign on device</source>
- <context-group purpose="location"><context context-type="linenumber">211</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">209</context></context-group>
<note annotates="source" from="developer">&quot;device&quot; usually means a hardware wallet.</note>
</trans-unit>
- <trans-unit id="_msg697">
+ <trans-unit id="_msg722">
<source xml:space="preserve">Connect your hardware wallet first.</source>
- <context-group purpose="location"><context context-type="linenumber">214</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">212</context></context-group>
</trans-unit>
- <trans-unit id="_msg698">
+ <trans-unit id="_msg723">
<source xml:space="preserve">Set external signer script path in Options -&gt; Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">218</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">216</context></context-group>
<note annotates="source" from="developer">&quot;External signer&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg699">
+ <trans-unit id="_msg724">
<source xml:space="preserve">Cr&amp;eate Unsigned</source>
- <context-group purpose="location"><context context-type="linenumber">221</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">219</context></context-group>
</trans-unit>
- <trans-unit id="_msg700">
+ <trans-unit id="_msg725">
<source xml:space="preserve">Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <context-group purpose="location"><context context-type="linenumber">222</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">220</context></context-group>
</trans-unit>
- <trans-unit id="_msg701">
+ <trans-unit id="_msg726">
<source xml:space="preserve"> from wallet &apos;%1&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">312</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
</trans-unit>
- <trans-unit id="_msg702">
+ <trans-unit id="_msg727">
<source xml:space="preserve">%1 to &apos;%2&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg703">
+ <trans-unit id="_msg728">
<source xml:space="preserve">%1 to %2</source>
- <context-group purpose="location"><context context-type="linenumber">328</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
- <trans-unit id="_msg704">
+ <trans-unit id="_msg729">
<source xml:space="preserve">To review recipient list click &quot;Show Details…&quot;</source>
- <context-group purpose="location"><context context-type="linenumber">395</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">392</context></context-group>
</trans-unit>
- <trans-unit id="_msg705">
+ <trans-unit id="_msg730">
<source xml:space="preserve">Sign failed</source>
- <context-group purpose="location"><context context-type="linenumber">439</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">452</context></context-group>
</trans-unit>
- <trans-unit id="_msg706">
+ <trans-unit id="_msg731">
<source xml:space="preserve">External signer not found</source>
- <context-group purpose="location"><context context-type="linenumber">445</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">457</context></context-group>
<note annotates="source" from="developer">&quot;External signer&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg707">
+ <trans-unit id="_msg732">
<source xml:space="preserve">External signer failure</source>
- <context-group purpose="location"><context context-type="linenumber">451</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">462</context></context-group>
<note annotates="source" from="developer">&quot;External signer&quot; means using devices such as hardware wallets.</note>
</trans-unit>
- <trans-unit id="_msg708">
+ <trans-unit id="_msg733">
<source xml:space="preserve">Save Transaction Data</source>
- <context-group purpose="location"><context context-type="linenumber">509</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">428</context></context-group>
</trans-unit>
- <trans-unit id="_msg709">
+ <trans-unit id="_msg734">
<source xml:space="preserve">Partially Signed Transaction (Binary)</source>
- <context-group purpose="location"><context context-type="linenumber">511</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">430</context></context-group>
<note annotates="source" from="developer">Expanded name of the binary PSBT file format. See: BIP 174.</note>
</trans-unit>
- <trans-unit id="_msg710">
+ <trans-unit id="_msg735">
<source xml:space="preserve">PSBT saved</source>
- <context-group purpose="location"><context context-type="linenumber">518</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">437</context></context-group>
</trans-unit>
- <trans-unit id="_msg711">
+ <trans-unit id="_msg736">
<source xml:space="preserve">External balance:</source>
- <context-group purpose="location"><context context-type="linenumber">694</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">703</context></context-group>
</trans-unit>
- <trans-unit id="_msg712">
+ <trans-unit id="_msg737">
<source xml:space="preserve">or</source>
- <context-group purpose="location"><context context-type="linenumber">391</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">388</context></context-group>
</trans-unit>
- <trans-unit id="_msg713">
+ <trans-unit id="_msg738">
<source xml:space="preserve">You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
- <context-group purpose="location"><context context-type="linenumber">372</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">370</context></context-group>
</trans-unit>
- <trans-unit id="_msg714">
+ <trans-unit id="_msg739">
<source xml:space="preserve">Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <context-group purpose="location"><context context-type="linenumber">342</context></context-group>
+ <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 only create a PSBT. This string is displayed when private keys are disabled and an external signer is not available.</note>
</trans-unit>
- <trans-unit id="_msg715">
+ <trans-unit id="_msg740">
<source xml:space="preserve">Do you want to create this transaction?</source>
- <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
<note annotates="source" from="developer">Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</note>
</trans-unit>
- <trans-unit id="_msg716">
+ <trans-unit id="_msg741">
<source xml:space="preserve">Please, review your transaction. You can create and send this transaction or create a Partially Signed Bitcoin Transaction (PSBT), which you can save or copy and then sign with, e.g., an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <context-group purpose="location"><context context-type="linenumber">347</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">345</context></context-group>
<note annotates="source" from="developer">Text to inform a user attempting to create a transaction of their current options. At this stage, a user can send their transaction or create a PSBT. This string is displayed when both private keys and PSBT controls are enabled.</note>
</trans-unit>
- <trans-unit id="_msg717">
+ <trans-unit id="_msg742">
<source xml:space="preserve">Please, review your transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">348</context></context-group>
<note annotates="source" from="developer">Text to prompt a user to review the details of the transaction they are attempting to send.</note>
</trans-unit>
- <trans-unit id="_msg718">
+ <trans-unit id="_msg743">
<source xml:space="preserve">Transaction fee</source>
- <context-group purpose="location"><context context-type="linenumber">358</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">356</context></context-group>
</trans-unit>
- <trans-unit id="_msg719">
+ <trans-unit id="_msg744">
<source xml:space="preserve">Not signalling Replace-By-Fee, BIP-125.</source>
- <context-group purpose="location"><context context-type="linenumber">374</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">372</context></context-group>
</trans-unit>
- <trans-unit id="_msg720">
+ <trans-unit id="_msg745">
<source xml:space="preserve">Total Amount</source>
- <context-group purpose="location"><context context-type="linenumber">388</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">385</context></context-group>
</trans-unit>
- <trans-unit id="_msg721">
+ <trans-unit id="_msg746">
<source xml:space="preserve">Confirm send coins</source>
- <context-group purpose="location"><context context-type="linenumber">413</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">484</context></context-group>
</trans-unit>
- <trans-unit id="_msg722">
+ <trans-unit id="_msg747">
<source xml:space="preserve">Watch-only balance:</source>
- <context-group purpose="location"><context context-type="linenumber">697</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">706</context></context-group>
</trans-unit>
- <trans-unit id="_msg723">
+ <trans-unit id="_msg748">
<source xml:space="preserve">The recipient address is not valid. Please recheck.</source>
- <context-group purpose="location"><context context-type="linenumber">721</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">730</context></context-group>
</trans-unit>
- <trans-unit id="_msg724">
+ <trans-unit id="_msg749">
<source xml:space="preserve">The amount to pay must be larger than 0.</source>
- <context-group purpose="location"><context context-type="linenumber">724</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">733</context></context-group>
</trans-unit>
- <trans-unit id="_msg725">
+ <trans-unit id="_msg750">
<source xml:space="preserve">The amount exceeds your balance.</source>
- <context-group purpose="location"><context context-type="linenumber">727</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">736</context></context-group>
</trans-unit>
- <trans-unit id="_msg726">
+ <trans-unit id="_msg751">
<source xml:space="preserve">The total exceeds your balance when the %1 transaction fee is included.</source>
- <context-group purpose="location"><context context-type="linenumber">730</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">739</context></context-group>
</trans-unit>
- <trans-unit id="_msg727">
+ <trans-unit id="_msg752">
<source xml:space="preserve">Duplicate address found: addresses should only be used once each.</source>
- <context-group purpose="location"><context context-type="linenumber">733</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">742</context></context-group>
</trans-unit>
- <trans-unit id="_msg728">
+ <trans-unit id="_msg753">
<source xml:space="preserve">Transaction creation failed!</source>
- <context-group purpose="location"><context context-type="linenumber">736</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">745</context></context-group>
</trans-unit>
- <trans-unit id="_msg729">
+ <trans-unit id="_msg754">
<source xml:space="preserve">A fee higher than %1 is considered an absurdly high fee.</source>
- <context-group purpose="location"><context context-type="linenumber">740</context></context-group>
- </trans-unit>
- <trans-unit id="_msg730">
- <source xml:space="preserve">Payment request expired.</source>
- <context-group purpose="location"><context context-type="linenumber">743</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">749</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">867</context></context-group>
- <trans-unit id="_msg731[0]">
+ <context-group purpose="location"><context context-type="linenumber">872</context></context-group>
+ <trans-unit id="_msg755[0]">
<source xml:space="preserve">Estimated to begin confirmation within %n block(s).</source>
</trans-unit>
- <trans-unit id="_msg731[1]">
+ <trans-unit id="_msg755[1]">
<source xml:space="preserve">Estimated to begin confirmation within %n block(s).</source>
</trans-unit>
</group>
- <trans-unit id="_msg732">
+ <trans-unit id="_msg756">
<source xml:space="preserve">Warning: Invalid Bitcoin address</source>
- <context-group purpose="location"><context context-type="linenumber">968</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">973</context></context-group>
</trans-unit>
- <trans-unit id="_msg733">
+ <trans-unit id="_msg757">
<source xml:space="preserve">Warning: Unknown change address</source>
- <context-group purpose="location"><context context-type="linenumber">973</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">978</context></context-group>
</trans-unit>
- <trans-unit id="_msg734">
+ <trans-unit id="_msg758">
<source xml:space="preserve">Confirm custom change address</source>
- <context-group purpose="location"><context context-type="linenumber">976</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">981</context></context-group>
</trans-unit>
- <trans-unit id="_msg735">
+ <trans-unit id="_msg759">
<source xml:space="preserve">The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?</source>
- <context-group purpose="location"><context context-type="linenumber">976</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">981</context></context-group>
</trans-unit>
- <trans-unit id="_msg736">
+ <trans-unit id="_msg760">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">997</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">1002</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/sendcoinsentry.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendCoinsEntry">
- <trans-unit id="_msg737">
+ <trans-unit id="_msg761">
<source xml:space="preserve">A&amp;mount:</source>
- <context-group purpose="location"><context context-type="linenumber">155</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">705</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1238</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">151</context></context-group>
</trans-unit>
- <trans-unit id="_msg738">
+ <trans-unit id="_msg762">
<source xml:space="preserve">Pay &amp;To:</source>
- <context-group purpose="location"><context context-type="linenumber">39</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">35</context></context-group>
</trans-unit>
- <trans-unit id="_msg739">
+ <trans-unit id="_msg763">
<source xml:space="preserve">&amp;Label:</source>
- <context-group purpose="location"><context context-type="linenumber">132</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">128</context></context-group>
</trans-unit>
- <trans-unit id="_msg740">
+ <trans-unit id="_msg764">
<source xml:space="preserve">Choose previously used address</source>
- <context-group purpose="location"><context context-type="linenumber">64</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">60</context></context-group>
</trans-unit>
- <trans-unit id="_msg741">
+ <trans-unit id="_msg765">
<source xml:space="preserve">The Bitcoin address to send the payment to</source>
- <context-group purpose="location"><context context-type="linenumber">57</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg742">
+ <trans-unit id="_msg766">
<source xml:space="preserve">Alt+A</source>
- <context-group purpose="location"><context context-type="linenumber">80</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">76</context></context-group>
</trans-unit>
- <trans-unit id="_msg743">
+ <trans-unit id="_msg767">
<source xml:space="preserve">Paste address from clipboard</source>
- <context-group purpose="location"><context context-type="linenumber">87</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">83</context></context-group>
</trans-unit>
- <trans-unit id="_msg744">
+ <trans-unit id="_msg768">
<source xml:space="preserve">Alt+P</source>
- <context-group purpose="location"><context context-type="linenumber">103</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg745">
+ <trans-unit id="_msg769">
<source xml:space="preserve">Remove this entry</source>
- <context-group purpose="location"><context context-type="linenumber">110</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">672</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1205</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">106</context></context-group>
</trans-unit>
- <trans-unit id="_msg746">
+ <trans-unit id="_msg770">
<source xml:space="preserve">The amount to send in the selected unit</source>
- <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">166</context></context-group>
</trans-unit>
- <trans-unit id="_msg747">
+ <trans-unit id="_msg771">
<source xml:space="preserve">The fee will be deducted from the amount being sent. The recipient will receive less bitcoins than you enter in the amount field. If multiple recipients are selected, the fee is split equally.</source>
- <context-group purpose="location"><context context-type="linenumber">177</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
</trans-unit>
- <trans-unit id="_msg748">
+ <trans-unit id="_msg772">
<source xml:space="preserve">S&amp;ubtract fee from amount</source>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">176</context></context-group>
</trans-unit>
- <trans-unit id="_msg749">
+ <trans-unit id="_msg773">
<source xml:space="preserve">Use available balance</source>
- <context-group purpose="location"><context context-type="linenumber">187</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">183</context></context-group>
</trans-unit>
- <trans-unit id="_msg750">
+ <trans-unit id="_msg774">
<source xml:space="preserve">Message:</source>
- <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
- </trans-unit>
- <trans-unit id="_msg751">
- <source xml:space="preserve">This is an unauthenticated payment request.</source>
- <context-group purpose="location"><context context-type="linenumber">639</context></context-group>
- </trans-unit>
- <trans-unit id="_msg752">
- <source xml:space="preserve">This is an authenticated payment request.</source>
- <context-group purpose="location"><context context-type="linenumber">1168</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
</trans-unit>
- <trans-unit id="_msg753">
+ <trans-unit id="_msg775">
<source xml:space="preserve">Enter a label for this address to add it to the list of used addresses</source>
- <context-group purpose="location"><context context-type="linenumber">145</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">148</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">141</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">144</context></context-group>
</trans-unit>
- <trans-unit id="_msg754">
+ <trans-unit id="_msg776">
<source xml:space="preserve">A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
- <context-group purpose="location"><context context-type="linenumber">206</context></context-group>
- </trans-unit>
- <trans-unit id="_msg755">
- <source xml:space="preserve">Pay To:</source>
- <context-group purpose="location"><context context-type="linenumber">654</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1183</context></context-group>
- </trans-unit>
- <trans-unit id="_msg756">
- <source xml:space="preserve">Memo:</source>
- <context-group purpose="location"><context context-type="linenumber">688</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">1221</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">202</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../sendcoinsdialog.h" datatype="c" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SendConfirmationDialog">
- <trans-unit id="_msg757">
+ <trans-unit id="_msg777">
<source xml:space="preserve">Send</source>
- <context-group purpose="location"><context context-type="linenumber">131</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">144</context></context-group>
</trans-unit>
- <trans-unit id="_msg758">
+ <trans-unit id="_msg778">
<source xml:space="preserve">Create Unsigned</source>
- <context-group purpose="location"><context context-type="linenumber">133</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/signverifymessagedialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SignVerifyMessageDialog">
- <trans-unit id="_msg759">
+ <trans-unit id="_msg779">
<source xml:space="preserve">Signatures - Sign / Verify a Message</source>
<context-group purpose="location"><context context-type="linenumber">14</context></context-group>
</trans-unit>
- <trans-unit id="_msg760">
+ <trans-unit id="_msg780">
<source xml:space="preserve">&amp;Sign Message</source>
<context-group purpose="location"><context context-type="linenumber">27</context></context-group>
</trans-unit>
- <trans-unit id="_msg761">
+ <trans-unit id="_msg781">
<source xml:space="preserve">You can sign messages/agreements with your addresses to prove you can receive bitcoins sent to them. Be careful not to sign anything vague or random, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</source>
<context-group purpose="location"><context context-type="linenumber">33</context></context-group>
</trans-unit>
- <trans-unit id="_msg762">
+ <trans-unit id="_msg782">
<source xml:space="preserve">The Bitcoin address to sign the message with</source>
<context-group purpose="location"><context context-type="linenumber">51</context></context-group>
</trans-unit>
- <trans-unit id="_msg763">
+ <trans-unit id="_msg783">
<source xml:space="preserve">Choose previously used address</source>
<context-group purpose="location"><context context-type="linenumber">58</context></context-group>
<context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
- <trans-unit id="_msg764">
+ <trans-unit id="_msg784">
<source xml:space="preserve">Alt+A</source>
<context-group purpose="location"><context context-type="linenumber">68</context></context-group>
<context-group purpose="location"><context context-type="linenumber">284</context></context-group>
</trans-unit>
- <trans-unit id="_msg765">
+ <trans-unit id="_msg785">
<source xml:space="preserve">Paste address from clipboard</source>
<context-group purpose="location"><context context-type="linenumber">78</context></context-group>
</trans-unit>
- <trans-unit id="_msg766">
+ <trans-unit id="_msg786">
<source xml:space="preserve">Alt+P</source>
<context-group purpose="location"><context context-type="linenumber">88</context></context-group>
</trans-unit>
- <trans-unit id="_msg767">
+ <trans-unit id="_msg787">
<source xml:space="preserve">Enter the message you want to sign here</source>
<context-group purpose="location"><context context-type="linenumber">100</context></context-group>
<context-group purpose="location"><context context-type="linenumber">103</context></context-group>
</trans-unit>
- <trans-unit id="_msg768">
+ <trans-unit id="_msg788">
<source xml:space="preserve">Signature</source>
<context-group purpose="location"><context context-type="linenumber">110</context></context-group>
</trans-unit>
- <trans-unit id="_msg769">
+ <trans-unit id="_msg789">
<source xml:space="preserve">Copy the current signature to the system clipboard</source>
<context-group purpose="location"><context context-type="linenumber">140</context></context-group>
</trans-unit>
- <trans-unit id="_msg770">
+ <trans-unit id="_msg790">
<source xml:space="preserve">Sign the message to prove you own this Bitcoin address</source>
<context-group purpose="location"><context context-type="linenumber">161</context></context-group>
</trans-unit>
- <trans-unit id="_msg771">
+ <trans-unit id="_msg791">
<source xml:space="preserve">Sign &amp;Message</source>
<context-group purpose="location"><context context-type="linenumber">164</context></context-group>
</trans-unit>
- <trans-unit id="_msg772">
+ <trans-unit id="_msg792">
<source xml:space="preserve">Reset all sign message fields</source>
<context-group purpose="location"><context context-type="linenumber">178</context></context-group>
</trans-unit>
- <trans-unit id="_msg773">
+ <trans-unit id="_msg793">
<source xml:space="preserve">Clear &amp;All</source>
<context-group purpose="location"><context context-type="linenumber">181</context></context-group>
<context-group purpose="location"><context context-type="linenumber">338</context></context-group>
</trans-unit>
- <trans-unit id="_msg774">
+ <trans-unit id="_msg794">
<source xml:space="preserve">&amp;Verify Message</source>
<context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
- <trans-unit id="_msg775">
+ <trans-unit id="_msg795">
<source xml:space="preserve">Enter the receiver&apos;s address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
<context-group purpose="location"><context context-type="linenumber">246</context></context-group>
</trans-unit>
- <trans-unit id="_msg776">
+ <trans-unit id="_msg796">
<source xml:space="preserve">The Bitcoin address the message was signed with</source>
<context-group purpose="location"><context context-type="linenumber">267</context></context-group>
</trans-unit>
- <trans-unit id="_msg777">
+ <trans-unit id="_msg797">
<source xml:space="preserve">The signed message to verify</source>
<context-group purpose="location"><context context-type="linenumber">296</context></context-group>
<context-group purpose="location"><context context-type="linenumber">299</context></context-group>
</trans-unit>
- <trans-unit id="_msg778">
+ <trans-unit id="_msg798">
<source xml:space="preserve">The signature given when the message was signed</source>
<context-group purpose="location"><context context-type="linenumber">306</context></context-group>
<context-group purpose="location"><context context-type="linenumber">309</context></context-group>
</trans-unit>
- <trans-unit id="_msg779">
+ <trans-unit id="_msg799">
<source xml:space="preserve">Verify the message to ensure it was signed with the specified Bitcoin address</source>
<context-group purpose="location"><context context-type="linenumber">318</context></context-group>
</trans-unit>
- <trans-unit id="_msg780">
+ <trans-unit id="_msg800">
<source xml:space="preserve">Verify &amp;Message</source>
<context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg781">
+ <trans-unit id="_msg801">
<source xml:space="preserve">Reset all verify message fields</source>
<context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg782">
+ <trans-unit id="_msg802">
<source xml:space="preserve">Click &quot;Sign Message&quot; to generate signature</source>
<context-group purpose="location"><context context-type="linenumber">125</context></context-group>
</trans-unit>
@@ -3561,61 +3679,61 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../signverifymessagedialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SignVerifyMessageDialog">
- <trans-unit id="_msg783">
+ <trans-unit id="_msg803">
<source xml:space="preserve">The entered address is invalid.</source>
<context-group purpose="location"><context context-type="linenumber">120</context></context-group>
<context-group purpose="location"><context context-type="linenumber">219</context></context-group>
</trans-unit>
- <trans-unit id="_msg784">
+ <trans-unit id="_msg804">
<source xml:space="preserve">Please check the address and try again.</source>
<context-group purpose="location"><context context-type="linenumber">120</context></context-group>
<context-group purpose="location"><context context-type="linenumber">127</context></context-group>
<context-group purpose="location"><context context-type="linenumber">220</context></context-group>
<context-group purpose="location"><context context-type="linenumber">227</context></context-group>
</trans-unit>
- <trans-unit id="_msg785">
+ <trans-unit id="_msg805">
<source xml:space="preserve">The entered address does not refer to a key.</source>
<context-group purpose="location"><context context-type="linenumber">127</context></context-group>
<context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg786">
+ <trans-unit id="_msg806">
<source xml:space="preserve">Wallet unlock was cancelled.</source>
<context-group purpose="location"><context context-type="linenumber">135</context></context-group>
</trans-unit>
- <trans-unit id="_msg787">
+ <trans-unit id="_msg807">
<source xml:space="preserve">No error</source>
<context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg788">
+ <trans-unit id="_msg808">
<source xml:space="preserve">Private key for the entered address is not available.</source>
<context-group purpose="location"><context context-type="linenumber">149</context></context-group>
</trans-unit>
- <trans-unit id="_msg789">
+ <trans-unit id="_msg809">
<source xml:space="preserve">Message signing failed.</source>
<context-group purpose="location"><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="_msg790">
+ <trans-unit id="_msg810">
<source xml:space="preserve">Message signed.</source>
<context-group purpose="location"><context context-type="linenumber">164</context></context-group>
</trans-unit>
- <trans-unit id="_msg791">
+ <trans-unit id="_msg811">
<source xml:space="preserve">The signature could not be decoded.</source>
<context-group purpose="location"><context context-type="linenumber">233</context></context-group>
</trans-unit>
- <trans-unit id="_msg792">
+ <trans-unit id="_msg812">
<source xml:space="preserve">Please check the signature and try again.</source>
<context-group purpose="location"><context context-type="linenumber">234</context></context-group>
<context-group purpose="location"><context context-type="linenumber">241</context></context-group>
</trans-unit>
- <trans-unit id="_msg793">
+ <trans-unit id="_msg813">
<source xml:space="preserve">The signature did not match the message digest.</source>
<context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
- <trans-unit id="_msg794">
+ <trans-unit id="_msg814">
<source xml:space="preserve">Message verification failed.</source>
<context-group purpose="location"><context context-type="linenumber">246</context></context-group>
</trans-unit>
- <trans-unit id="_msg795">
+ <trans-unit id="_msg815">
<source xml:space="preserve">Message verified.</source>
<context-group purpose="location"><context context-type="linenumber">214</context></context-group>
</trans-unit>
@@ -3623,11 +3741,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../splashscreen.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="SplashScreen">
- <trans-unit id="_msg796">
+ <trans-unit id="_msg816">
<source xml:space="preserve">(press q to shutdown and continue later)</source>
<context-group purpose="location"><context context-type="linenumber">187</context></context-group>
</trans-unit>
- <trans-unit id="_msg797">
+ <trans-unit id="_msg817">
<source xml:space="preserve">press q to shutdown</source>
<context-group purpose="location"><context context-type="linenumber">188</context></context-group>
</trans-unit>
@@ -3635,7 +3753,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../trafficgraphwidget.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TrafficGraphWidget">
- <trans-unit id="_msg798">
+ <trans-unit id="_msg818">
<source xml:space="preserve">kB/s</source>
<context-group purpose="location"><context context-type="linenumber">79</context></context-group>
</trans-unit>
@@ -3643,190 +3761,192 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../transactiondesc.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionDesc">
- <trans-unit id="_msg799">
+ <trans-unit id="_msg819">
<source xml:space="preserve">conflicted with a transaction with %1 confirmations</source>
- <context-group purpose="location"><context context-type="linenumber">40</context></context-group>
- </trans-unit>
- <trans-unit id="_msg800">
- <source xml:space="preserve">0/unconfirmed, %1</source>
<context-group purpose="location"><context context-type="linenumber">43</context></context-group>
+ <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</note>
</trans-unit>
- <trans-unit id="_msg801">
- <source xml:space="preserve">in memory pool</source>
- <context-group purpose="location"><context context-type="linenumber">43</context></context-group>
+ <trans-unit id="_msg820">
+ <source xml:space="preserve">0/unconfirmed, in memory pool</source>
+ <context-group purpose="location"><context context-type="linenumber">50</context></context-group>
+ <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</note>
</trans-unit>
- <trans-unit id="_msg802">
- <source xml:space="preserve">not in memory pool</source>
- <context-group purpose="location"><context context-type="linenumber">43</context></context-group>
+ <trans-unit id="_msg821">
+ <source xml:space="preserve">0/unconfirmed, not in memory pool</source>
+ <context-group purpose="location"><context context-type="linenumber">55</context></context-group>
+ <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</note>
</trans-unit>
- <trans-unit id="_msg803">
+ <trans-unit id="_msg822">
<source xml:space="preserve">abandoned</source>
- <context-group purpose="location"><context context-type="linenumber">42</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">61</context></context-group>
+ <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</note>
</trans-unit>
- <trans-unit id="_msg804">
+ <trans-unit id="_msg823">
<source xml:space="preserve">%1/unconfirmed</source>
- <context-group purpose="location"><context context-type="linenumber">45</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">69</context></context-group>
+ <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</note>
</trans-unit>
- <trans-unit id="_msg805">
+ <trans-unit id="_msg824">
<source xml:space="preserve">%1 confirmations</source>
- <context-group purpose="location"><context context-type="linenumber">47</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">74</context></context-group>
+ <note annotates="source" from="developer">Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</note>
</trans-unit>
- <trans-unit id="_msg806">
+ <trans-unit id="_msg825">
<source xml:space="preserve">Status</source>
- <context-group purpose="location"><context context-type="linenumber">98</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">124</context></context-group>
</trans-unit>
- <trans-unit id="_msg807">
+ <trans-unit id="_msg826">
<source xml:space="preserve">Date</source>
- <context-group purpose="location"><context context-type="linenumber">101</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
</trans-unit>
- <trans-unit id="_msg808">
+ <trans-unit id="_msg827">
<source xml:space="preserve">Source</source>
- <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">134</context></context-group>
</trans-unit>
- <trans-unit id="_msg809">
+ <trans-unit id="_msg828">
<source xml:space="preserve">Generated</source>
- <context-group purpose="location"><context context-type="linenumber">108</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">134</context></context-group>
</trans-unit>
- <trans-unit id="_msg810">
+ <trans-unit id="_msg829">
<source xml:space="preserve">From</source>
- <context-group purpose="location"><context context-type="linenumber">113</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">139</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">153</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
</trans-unit>
- <trans-unit id="_msg811">
+ <trans-unit id="_msg830">
<source xml:space="preserve">unknown</source>
- <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">153</context></context-group>
</trans-unit>
- <trans-unit id="_msg812">
+ <trans-unit id="_msg831">
<source xml:space="preserve">To</source>
- <context-group purpose="location"><context context-type="linenumber">128</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">148</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">218</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">154</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">244</context></context-group>
</trans-unit>
- <trans-unit id="_msg813">
+ <trans-unit id="_msg832">
<source xml:space="preserve">own address</source>
- <context-group purpose="location"><context context-type="linenumber">130</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">156</context></context-group>
</trans-unit>
- <trans-unit id="_msg814">
+ <trans-unit id="_msg833">
<source xml:space="preserve">watch-only</source>
- <context-group purpose="location"><context context-type="linenumber">130</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">156</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
</trans-unit>
- <trans-unit id="_msg815">
+ <trans-unit id="_msg834">
<source xml:space="preserve">label</source>
- <context-group purpose="location"><context context-type="linenumber">132</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">158</context></context-group>
</trans-unit>
- <trans-unit id="_msg816">
+ <trans-unit id="_msg835">
<source xml:space="preserve">Credit</source>
- <context-group purpose="location"><context context-type="linenumber">168</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">234</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">206</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
</trans-unit>
<group restype="x-gettext-plurals">
- <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
- <trans-unit id="_msg817[0]">
+ <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
+ <trans-unit id="_msg836[0]">
<source xml:space="preserve">matures in %n more block(s)</source>
</trans-unit>
- <trans-unit id="_msg817[1]">
+ <trans-unit id="_msg836[1]">
<source xml:space="preserve">matures in %n more block(s)</source>
</trans-unit>
</group>
- <trans-unit id="_msg818">
+ <trans-unit id="_msg837">
<source xml:space="preserve">not accepted</source>
- <context-group purpose="location"><context context-type="linenumber">172</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">198</context></context-group>
</trans-unit>
- <trans-unit id="_msg819">
+ <trans-unit id="_msg838">
<source xml:space="preserve">Debit</source>
- <context-group purpose="location"><context context-type="linenumber">232</context></context-group>
<context-group purpose="location"><context context-type="linenumber">258</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">284</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">347</context></context-group>
</trans-unit>
- <trans-unit id="_msg820">
+ <trans-unit id="_msg839">
<source xml:space="preserve">Total debit</source>
- <context-group purpose="location"><context context-type="linenumber">242</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
</trans-unit>
- <trans-unit id="_msg821">
+ <trans-unit id="_msg840">
<source xml:space="preserve">Total credit</source>
- <context-group purpose="location"><context context-type="linenumber">243</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">269</context></context-group>
</trans-unit>
- <trans-unit id="_msg822">
+ <trans-unit id="_msg841">
<source xml:space="preserve">Transaction fee</source>
- <context-group purpose="location"><context context-type="linenumber">248</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
- <trans-unit id="_msg823">
+ <trans-unit id="_msg842">
<source xml:space="preserve">Net amount</source>
- <context-group purpose="location"><context context-type="linenumber">270</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
</trans-unit>
- <trans-unit id="_msg824">
+ <trans-unit id="_msg843">
<source xml:space="preserve">Message</source>
- <context-group purpose="location"><context context-type="linenumber">276</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">288</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
</trans-unit>
- <trans-unit id="_msg825">
+ <trans-unit id="_msg844">
<source xml:space="preserve">Comment</source>
- <context-group purpose="location"><context context-type="linenumber">278</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">304</context></context-group>
</trans-unit>
- <trans-unit id="_msg826">
+ <trans-unit id="_msg845">
<source xml:space="preserve">Transaction ID</source>
- <context-group purpose="location"><context context-type="linenumber">280</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">306</context></context-group>
</trans-unit>
- <trans-unit id="_msg827">
+ <trans-unit id="_msg846">
<source xml:space="preserve">Transaction total size</source>
- <context-group purpose="location"><context context-type="linenumber">281</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">307</context></context-group>
</trans-unit>
- <trans-unit id="_msg828">
+ <trans-unit id="_msg847">
<source xml:space="preserve">Transaction virtual size</source>
- <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
</trans-unit>
- <trans-unit id="_msg829">
+ <trans-unit id="_msg848">
<source xml:space="preserve">Output index</source>
- <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">309</context></context-group>
</trans-unit>
- <trans-unit id="_msg830">
+ <trans-unit id="_msg849">
<source xml:space="preserve"> (Certificate was not verified)</source>
- <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
</trans-unit>
- <trans-unit id="_msg831">
+ <trans-unit id="_msg850">
<source xml:space="preserve">Merchant</source>
- <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">328</context></context-group>
</trans-unit>
- <trans-unit id="_msg832">
+ <trans-unit id="_msg851">
<source xml:space="preserve">Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to &quot;not accepted&quot; and it won&apos;t be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
</trans-unit>
- <trans-unit id="_msg833">
+ <trans-unit id="_msg852">
<source xml:space="preserve">Debug information</source>
- <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">344</context></context-group>
</trans-unit>
- <trans-unit id="_msg834">
+ <trans-unit id="_msg853">
<source xml:space="preserve">Transaction</source>
- <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
</trans-unit>
- <trans-unit id="_msg835">
+ <trans-unit id="_msg854">
<source xml:space="preserve">Inputs</source>
- <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">355</context></context-group>
</trans-unit>
- <trans-unit id="_msg836">
+ <trans-unit id="_msg855">
<source xml:space="preserve">Amount</source>
- <context-group purpose="location"><context context-type="linenumber">350</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">376</context></context-group>
</trans-unit>
- <trans-unit id="_msg837">
+ <trans-unit id="_msg856">
<source xml:space="preserve">true</source>
- <context-group purpose="location"><context context-type="linenumber">351</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">377</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">378</context></context-group>
</trans-unit>
- <trans-unit id="_msg838">
+ <trans-unit id="_msg857">
<source xml:space="preserve">false</source>
- <context-group purpose="location"><context context-type="linenumber">351</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">352</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">377</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">378</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../forms/transactiondescdialog.ui" datatype="x-trolltech-designer-ui" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionDescDialog">
- <trans-unit id="_msg839">
+ <trans-unit id="_msg858">
<source xml:space="preserve">This pane shows a detailed description of the transaction</source>
<context-group purpose="location"><context context-type="linenumber">20</context></context-group>
</trans-unit>
@@ -3834,7 +3954,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../transactiondescdialog.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionDescDialog">
- <trans-unit id="_msg840">
+ <trans-unit id="_msg859">
<source xml:space="preserve">Details for %1</source>
<context-group purpose="location"><context context-type="linenumber">18</context></context-group>
</trans-unit>
@@ -3842,266 +3962,266 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../transactiontablemodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionTableModel">
- <trans-unit id="_msg841">
+ <trans-unit id="_msg860">
<source xml:space="preserve">Date</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg842">
+ <trans-unit id="_msg861">
<source xml:space="preserve">Type</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg843">
+ <trans-unit id="_msg862">
<source xml:space="preserve">Label</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg844">
+ <trans-unit id="_msg863">
<source xml:space="preserve">Unconfirmed</source>
- <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg845">
+ <trans-unit id="_msg864">
<source xml:space="preserve">Abandoned</source>
- <context-group purpose="location"><context context-type="linenumber">323</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
</trans-unit>
- <trans-unit id="_msg846">
+ <trans-unit id="_msg865">
<source xml:space="preserve">Confirming (%1 of %2 recommended confirmations)</source>
- <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">327</context></context-group>
</trans-unit>
- <trans-unit id="_msg847">
+ <trans-unit id="_msg866">
<source xml:space="preserve">Confirmed (%1 confirmations)</source>
- <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
</trans-unit>
- <trans-unit id="_msg848">
+ <trans-unit id="_msg867">
<source xml:space="preserve">Conflicted</source>
- <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">333</context></context-group>
</trans-unit>
- <trans-unit id="_msg849">
+ <trans-unit id="_msg868">
<source xml:space="preserve">Immature (%1 confirmations, will be available after %2)</source>
- <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
</trans-unit>
- <trans-unit id="_msg850">
+ <trans-unit id="_msg869">
<source xml:space="preserve">Generated but not accepted</source>
- <context-group purpose="location"><context context-type="linenumber">338</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
</trans-unit>
- <trans-unit id="_msg851">
+ <trans-unit id="_msg870">
<source xml:space="preserve">Received with</source>
- <context-group purpose="location"><context context-type="linenumber">377</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">378</context></context-group>
</trans-unit>
- <trans-unit id="_msg852">
+ <trans-unit id="_msg871">
<source xml:space="preserve">Received from</source>
- <context-group purpose="location"><context context-type="linenumber">379</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">380</context></context-group>
</trans-unit>
- <trans-unit id="_msg853">
+ <trans-unit id="_msg872">
<source xml:space="preserve">Sent to</source>
- <context-group purpose="location"><context context-type="linenumber">382</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">383</context></context-group>
</trans-unit>
- <trans-unit id="_msg854">
+ <trans-unit id="_msg873">
<source xml:space="preserve">Payment to yourself</source>
- <context-group purpose="location"><context context-type="linenumber">384</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">385</context></context-group>
</trans-unit>
- <trans-unit id="_msg855">
+ <trans-unit id="_msg874">
<source xml:space="preserve">Mined</source>
- <context-group purpose="location"><context context-type="linenumber">386</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">387</context></context-group>
</trans-unit>
- <trans-unit id="_msg856">
+ <trans-unit id="_msg875">
<source xml:space="preserve">watch-only</source>
- <context-group purpose="location"><context context-type="linenumber">414</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">415</context></context-group>
</trans-unit>
- <trans-unit id="_msg857">
+ <trans-unit id="_msg876">
<source xml:space="preserve">(n/a)</source>
- <context-group purpose="location"><context context-type="linenumber">430</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">431</context></context-group>
</trans-unit>
- <trans-unit id="_msg858">
+ <trans-unit id="_msg877">
<source xml:space="preserve">(no label)</source>
- <context-group purpose="location"><context context-type="linenumber">637</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">638</context></context-group>
</trans-unit>
- <trans-unit id="_msg859">
+ <trans-unit id="_msg878">
<source xml:space="preserve">Transaction status. Hover over this field to show number of confirmations.</source>
- <context-group purpose="location"><context context-type="linenumber">676</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">677</context></context-group>
</trans-unit>
- <trans-unit id="_msg860">
+ <trans-unit id="_msg879">
<source xml:space="preserve">Date and time that the transaction was received.</source>
- <context-group purpose="location"><context context-type="linenumber">678</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">679</context></context-group>
</trans-unit>
- <trans-unit id="_msg861">
+ <trans-unit id="_msg880">
<source xml:space="preserve">Type of transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">680</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">681</context></context-group>
</trans-unit>
- <trans-unit id="_msg862">
+ <trans-unit id="_msg881">
<source xml:space="preserve">Whether or not a watch-only address is involved in this transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">682</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">683</context></context-group>
</trans-unit>
- <trans-unit id="_msg863">
+ <trans-unit id="_msg882">
<source xml:space="preserve">User-defined intent/purpose of the transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">684</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">685</context></context-group>
</trans-unit>
- <trans-unit id="_msg864">
+ <trans-unit id="_msg883">
<source xml:space="preserve">Amount removed from or added to balance.</source>
- <context-group purpose="location"><context context-type="linenumber">686</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">687</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../transactionview.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="TransactionView">
- <trans-unit id="_msg865">
+ <trans-unit id="_msg884">
<source xml:space="preserve">All</source>
<context-group purpose="location"><context context-type="linenumber">73</context></context-group>
<context-group purpose="location"><context context-type="linenumber">89</context></context-group>
</trans-unit>
- <trans-unit id="_msg866">
+ <trans-unit id="_msg885">
<source xml:space="preserve">Today</source>
<context-group purpose="location"><context context-type="linenumber">74</context></context-group>
</trans-unit>
- <trans-unit id="_msg867">
+ <trans-unit id="_msg886">
<source xml:space="preserve">This week</source>
<context-group purpose="location"><context context-type="linenumber">75</context></context-group>
</trans-unit>
- <trans-unit id="_msg868">
+ <trans-unit id="_msg887">
<source xml:space="preserve">This month</source>
<context-group purpose="location"><context context-type="linenumber">76</context></context-group>
</trans-unit>
- <trans-unit id="_msg869">
+ <trans-unit id="_msg888">
<source xml:space="preserve">Last month</source>
<context-group purpose="location"><context context-type="linenumber">77</context></context-group>
</trans-unit>
- <trans-unit id="_msg870">
+ <trans-unit id="_msg889">
<source xml:space="preserve">This year</source>
<context-group purpose="location"><context context-type="linenumber">78</context></context-group>
</trans-unit>
- <trans-unit id="_msg871">
+ <trans-unit id="_msg890">
<source xml:space="preserve">Received with</source>
<context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
- <trans-unit id="_msg872">
+ <trans-unit id="_msg891">
<source xml:space="preserve">Sent to</source>
<context-group purpose="location"><context context-type="linenumber">92</context></context-group>
</trans-unit>
- <trans-unit id="_msg873">
+ <trans-unit id="_msg892">
<source xml:space="preserve">To yourself</source>
<context-group purpose="location"><context context-type="linenumber">94</context></context-group>
</trans-unit>
- <trans-unit id="_msg874">
+ <trans-unit id="_msg893">
<source xml:space="preserve">Mined</source>
<context-group purpose="location"><context context-type="linenumber">95</context></context-group>
</trans-unit>
- <trans-unit id="_msg875">
+ <trans-unit id="_msg894">
<source xml:space="preserve">Other</source>
<context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg876">
+ <trans-unit id="_msg895">
<source xml:space="preserve">Enter address, transaction id, or label to search</source>
<context-group purpose="location"><context context-type="linenumber">101</context></context-group>
</trans-unit>
- <trans-unit id="_msg877">
+ <trans-unit id="_msg896">
<source xml:space="preserve">Min amount</source>
<context-group purpose="location"><context context-type="linenumber">105</context></context-group>
</trans-unit>
- <trans-unit id="_msg878">
+ <trans-unit id="_msg897">
<source xml:space="preserve">Range…</source>
<context-group purpose="location"><context context-type="linenumber">79</context></context-group>
</trans-unit>
- <trans-unit id="_msg879">
+ <trans-unit id="_msg898">
<source xml:space="preserve">&amp;Copy address</source>
<context-group purpose="location"><context context-type="linenumber">169</context></context-group>
</trans-unit>
- <trans-unit id="_msg880">
+ <trans-unit id="_msg899">
<source xml:space="preserve">Copy &amp;label</source>
<context-group purpose="location"><context context-type="linenumber">170</context></context-group>
</trans-unit>
- <trans-unit id="_msg881">
+ <trans-unit id="_msg900">
<source xml:space="preserve">Copy &amp;amount</source>
<context-group purpose="location"><context context-type="linenumber">171</context></context-group>
</trans-unit>
- <trans-unit id="_msg882">
+ <trans-unit id="_msg901">
<source xml:space="preserve">Copy transaction &amp;ID</source>
<context-group purpose="location"><context context-type="linenumber">172</context></context-group>
</trans-unit>
- <trans-unit id="_msg883">
+ <trans-unit id="_msg902">
<source xml:space="preserve">Copy &amp;raw transaction</source>
<context-group purpose="location"><context context-type="linenumber">173</context></context-group>
</trans-unit>
- <trans-unit id="_msg884">
+ <trans-unit id="_msg903">
<source xml:space="preserve">Copy full transaction &amp;details</source>
<context-group purpose="location"><context context-type="linenumber">174</context></context-group>
</trans-unit>
- <trans-unit id="_msg885">
+ <trans-unit id="_msg904">
<source xml:space="preserve">&amp;Show transaction details</source>
<context-group purpose="location"><context context-type="linenumber">175</context></context-group>
</trans-unit>
- <trans-unit id="_msg886">
+ <trans-unit id="_msg905">
<source xml:space="preserve">Increase transaction &amp;fee</source>
<context-group purpose="location"><context context-type="linenumber">177</context></context-group>
</trans-unit>
- <trans-unit id="_msg887">
+ <trans-unit id="_msg906">
<source xml:space="preserve">A&amp;bandon transaction</source>
<context-group purpose="location"><context context-type="linenumber">180</context></context-group>
</trans-unit>
- <trans-unit id="_msg888">
+ <trans-unit id="_msg907">
<source xml:space="preserve">&amp;Edit address label</source>
<context-group purpose="location"><context context-type="linenumber">181</context></context-group>
</trans-unit>
- <trans-unit id="_msg889">
+ <trans-unit id="_msg908">
<source xml:space="preserve">Show in %1</source>
<context-group purpose="location"><context context-type="linenumber">240</context></context-group>
<note annotates="source" from="developer">Transactions table context menu action to show the selected transaction in a third-party block explorer. %1 is a stand-in argument for the URL of the explorer.</note>
</trans-unit>
- <trans-unit id="_msg890">
+ <trans-unit id="_msg909">
<source xml:space="preserve">Export Transaction History</source>
<context-group purpose="location"><context context-type="linenumber">359</context></context-group>
</trans-unit>
- <trans-unit id="_msg891">
+ <trans-unit id="_msg910">
<source xml:space="preserve">Comma separated file</source>
<context-group purpose="location"><context context-type="linenumber">362</context></context-group>
<note annotates="source" from="developer">Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</note>
</trans-unit>
- <trans-unit id="_msg892">
+ <trans-unit id="_msg911">
<source xml:space="preserve">Confirmed</source>
<context-group purpose="location"><context context-type="linenumber">371</context></context-group>
</trans-unit>
- <trans-unit id="_msg893">
+ <trans-unit id="_msg912">
<source xml:space="preserve">Watch-only</source>
<context-group purpose="location"><context context-type="linenumber">373</context></context-group>
</trans-unit>
- <trans-unit id="_msg894">
+ <trans-unit id="_msg913">
<source xml:space="preserve">Date</source>
<context-group purpose="location"><context context-type="linenumber">374</context></context-group>
</trans-unit>
- <trans-unit id="_msg895">
+ <trans-unit id="_msg914">
<source xml:space="preserve">Type</source>
<context-group purpose="location"><context context-type="linenumber">375</context></context-group>
</trans-unit>
- <trans-unit id="_msg896">
+ <trans-unit id="_msg915">
<source xml:space="preserve">Label</source>
<context-group purpose="location"><context context-type="linenumber">376</context></context-group>
</trans-unit>
- <trans-unit id="_msg897">
+ <trans-unit id="_msg916">
<source xml:space="preserve">Address</source>
<context-group purpose="location"><context context-type="linenumber">377</context></context-group>
</trans-unit>
- <trans-unit id="_msg898">
+ <trans-unit id="_msg917">
<source xml:space="preserve">ID</source>
<context-group purpose="location"><context context-type="linenumber">379</context></context-group>
</trans-unit>
- <trans-unit id="_msg899">
+ <trans-unit id="_msg918">
<source xml:space="preserve">Exporting Failed</source>
<context-group purpose="location"><context context-type="linenumber">382</context></context-group>
</trans-unit>
- <trans-unit id="_msg900">
+ <trans-unit id="_msg919">
<source xml:space="preserve">There was an error trying to save the transaction history to %1.</source>
<context-group purpose="location"><context context-type="linenumber">382</context></context-group>
</trans-unit>
- <trans-unit id="_msg901">
+ <trans-unit id="_msg920">
<source xml:space="preserve">Exporting Successful</source>
<context-group purpose="location"><context context-type="linenumber">386</context></context-group>
</trans-unit>
- <trans-unit id="_msg902">
+ <trans-unit id="_msg921">
<source xml:space="preserve">The transaction history was successfully saved to %1.</source>
<context-group purpose="location"><context context-type="linenumber">386</context></context-group>
</trans-unit>
- <trans-unit id="_msg903">
+ <trans-unit id="_msg922">
<source xml:space="preserve">Range:</source>
<context-group purpose="location"><context context-type="linenumber">558</context></context-group>
</trans-unit>
- <trans-unit id="_msg904">
+ <trans-unit id="_msg923">
<source xml:space="preserve">to</source>
<context-group purpose="location"><context context-type="linenumber">566</context></context-group>
</trans-unit>
@@ -4109,810 +4229,936 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of &quot;100
</body></file>
<file original="../walletframe.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletFrame">
- <trans-unit id="_msg905">
+ <trans-unit id="_msg924">
<source xml:space="preserve">No wallet has been loaded.
Go to File &gt; Open Wallet to load a wallet.
- OR -</source>
<context-group purpose="location"><context context-type="linenumber">45</context></context-group>
</trans-unit>
- <trans-unit id="_msg906">
+ <trans-unit id="_msg925">
<source xml:space="preserve">Create a new wallet</source>
<context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg907">
+ <trans-unit id="_msg926">
<source xml:space="preserve">Error</source>
- <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">213</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">211</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
</trans-unit>
- <trans-unit id="_msg908">
+ <trans-unit id="_msg927">
<source xml:space="preserve">Unable to decode PSBT from clipboard (invalid base64)</source>
- <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
</trans-unit>
- <trans-unit id="_msg909">
+ <trans-unit id="_msg928">
<source xml:space="preserve">Load Transaction Data</source>
- <context-group purpose="location"><context context-type="linenumber">209</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">207</context></context-group>
</trans-unit>
- <trans-unit id="_msg910">
+ <trans-unit id="_msg929">
<source xml:space="preserve">Partially Signed Transaction (*.psbt)</source>
- <context-group purpose="location"><context context-type="linenumber">210</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">208</context></context-group>
</trans-unit>
- <trans-unit id="_msg911">
+ <trans-unit id="_msg930">
<source xml:space="preserve">PSBT file must be smaller than 100 MiB</source>
- <context-group purpose="location"><context context-type="linenumber">213</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">211</context></context-group>
</trans-unit>
- <trans-unit id="_msg912">
+ <trans-unit id="_msg931">
<source xml:space="preserve">Unable to decode PSBT</source>
- <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../walletmodel.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletModel">
- <trans-unit id="_msg913">
+ <trans-unit id="_msg932">
<source xml:space="preserve">Send Coins</source>
- <context-group purpose="location"><context context-type="linenumber">221</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">232</context></context-group>
</trans-unit>
- <trans-unit id="_msg914">
+ <trans-unit id="_msg933">
<source xml:space="preserve">Fee bump error</source>
- <context-group purpose="location"><context context-type="linenumber">481</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">533</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">548</context></context-group>
- <context-group purpose="location"><context context-type="linenumber">553</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">495</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">547</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">562</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">567</context></context-group>
</trans-unit>
- <trans-unit id="_msg915">
+ <trans-unit id="_msg934">
<source xml:space="preserve">Increasing transaction fee failed</source>
- <context-group purpose="location"><context context-type="linenumber">481</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">495</context></context-group>
</trans-unit>
- <trans-unit id="_msg916">
+ <trans-unit id="_msg935">
<source xml:space="preserve">Do you want to increase the fee?</source>
- <context-group purpose="location"><context context-type="linenumber">488</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">502</context></context-group>
<note annotates="source" from="developer">Asks a user if they would like to manually increase the fee of a transaction that has already been created.</note>
</trans-unit>
- <trans-unit id="_msg917">
+ <trans-unit id="_msg936">
<source xml:space="preserve">Current fee:</source>
- <context-group purpose="location"><context context-type="linenumber">492</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">506</context></context-group>
</trans-unit>
- <trans-unit id="_msg918">
+ <trans-unit id="_msg937">
<source xml:space="preserve">Increase:</source>
- <context-group purpose="location"><context context-type="linenumber">496</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">510</context></context-group>
</trans-unit>
- <trans-unit id="_msg919">
+ <trans-unit id="_msg938">
<source xml:space="preserve">New fee:</source>
- <context-group purpose="location"><context context-type="linenumber">500</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">514</context></context-group>
</trans-unit>
- <trans-unit id="_msg920">
+ <trans-unit id="_msg939">
<source xml:space="preserve">Warning: This may pay the additional fee by reducing change outputs or adding inputs, when necessary. It may add a new change output if one does not already exist. These changes may potentially leak privacy.</source>
- <context-group purpose="location"><context context-type="linenumber">508</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">522</context></context-group>
</trans-unit>
- <trans-unit id="_msg921">
+ <trans-unit id="_msg940">
<source xml:space="preserve">Confirm fee bump</source>
- <context-group purpose="location"><context context-type="linenumber">511</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">525</context></context-group>
</trans-unit>
- <trans-unit id="_msg922">
+ <trans-unit id="_msg941">
<source xml:space="preserve">Can&apos;t draft transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">533</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">547</context></context-group>
</trans-unit>
- <trans-unit id="_msg923">
+ <trans-unit id="_msg942">
<source xml:space="preserve">PSBT copied</source>
- <context-group purpose="location"><context context-type="linenumber">540</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">554</context></context-group>
</trans-unit>
- <trans-unit id="_msg924">
+ <trans-unit id="_msg943">
<source xml:space="preserve">Can&apos;t sign transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">548</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">562</context></context-group>
</trans-unit>
- <trans-unit id="_msg925">
+ <trans-unit id="_msg944">
<source xml:space="preserve">Could not commit transaction</source>
- <context-group purpose="location"><context context-type="linenumber">553</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">567</context></context-group>
</trans-unit>
- <trans-unit id="_msg926">
+ <trans-unit id="_msg945">
<source xml:space="preserve">Can&apos;t display address</source>
- <context-group purpose="location"><context context-type="linenumber">567</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">581</context></context-group>
</trans-unit>
- <trans-unit id="_msg927">
+ <trans-unit id="_msg946">
<source xml:space="preserve">default wallet</source>
- <context-group purpose="location"><context context-type="linenumber">585</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">599</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../walletview.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="WalletView">
- <trans-unit id="_msg928">
+ <trans-unit id="_msg947">
<source xml:space="preserve">&amp;Export</source>
- <context-group purpose="location"><context context-type="linenumber">52</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">51</context></context-group>
</trans-unit>
- <trans-unit id="_msg929">
+ <trans-unit id="_msg948">
<source xml:space="preserve">Export the data in the current tab to a file</source>
- <context-group purpose="location"><context context-type="linenumber">53</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">52</context></context-group>
</trans-unit>
- <trans-unit id="_msg930">
+ <trans-unit id="_msg949">
<source xml:space="preserve">Backup Wallet</source>
- <context-group purpose="location"><context context-type="linenumber">217</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">214</context></context-group>
</trans-unit>
- <trans-unit id="_msg931">
+ <trans-unit id="_msg950">
<source xml:space="preserve">Wallet Data</source>
- <context-group purpose="location"><context context-type="linenumber">219</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">216</context></context-group>
<note annotates="source" from="developer">Name of the wallet data file format.</note>
</trans-unit>
- <trans-unit id="_msg932">
+ <trans-unit id="_msg951">
<source xml:space="preserve">Backup Failed</source>
- <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">222</context></context-group>
</trans-unit>
- <trans-unit id="_msg933">
+ <trans-unit id="_msg952">
<source xml:space="preserve">There was an error trying to save the wallet data to %1.</source>
- <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">222</context></context-group>
</trans-unit>
- <trans-unit id="_msg934">
+ <trans-unit id="_msg953">
<source xml:space="preserve">Backup Successful</source>
- <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg935">
+ <trans-unit id="_msg954">
<source xml:space="preserve">The wallet data was successfully saved to %1.</source>
- <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg936">
+ <trans-unit id="_msg955">
<source xml:space="preserve">Cancel</source>
- <context-group purpose="location"><context context-type="linenumber">266</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
</group>
</body></file>
<file original="../bitcoinstrings.cpp" datatype="cpp" source-language="en"><body>
<group restype="x-trolltech-linguist-context" resname="bitcoin-core">
- <trans-unit id="_msg937">
+ <trans-unit id="_msg956">
<source xml:space="preserve">The %s developers</source>
<context-group purpose="location"><context context-type="linenumber">12</context></context-group>
</trans-unit>
- <trans-unit id="_msg938">
+ <trans-unit id="_msg957">
<source xml:space="preserve">%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
<context-group purpose="location"><context context-type="linenumber">13</context></context-group>
</trans-unit>
- <trans-unit id="_msg939">
+ <trans-unit id="_msg958">
<source xml:space="preserve">-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">16</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">20</context></context-group>
</trans-unit>
- <trans-unit id="_msg940">
+ <trans-unit id="_msg959">
<source xml:space="preserve">Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
- <context-group purpose="location"><context context-type="linenumber">19</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">38</context></context-group>
</trans-unit>
- <trans-unit id="_msg941">
+ <trans-unit id="_msg960">
<source xml:space="preserve">Cannot obtain a lock on data directory %s. %s is probably already running.</source>
- <context-group purpose="location"><context context-type="linenumber">22</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">41</context></context-group>
</trans-unit>
- <trans-unit id="_msg942">
+ <trans-unit id="_msg961">
<source xml:space="preserve">Cannot upgrade a non HD split wallet from version %i to version %i without upgrading to support pre-split keypool. Please use version %i or no version specified.</source>
- <context-group purpose="location"><context context-type="linenumber">27</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">46</context></context-group>
</trans-unit>
- <trans-unit id="_msg943">
+ <trans-unit id="_msg962">
<source xml:space="preserve">Distributed under the MIT software license, see the accompanying file %s or %s</source>
- <context-group purpose="location"><context context-type="linenumber">31</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">50</context></context-group>
</trans-unit>
- <trans-unit id="_msg944">
+ <trans-unit id="_msg963">
<source xml:space="preserve">Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
- <context-group purpose="location"><context context-type="linenumber">37</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">56</context></context-group>
</trans-unit>
- <trans-unit id="_msg945">
+ <trans-unit id="_msg964">
<source xml:space="preserve">Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
- <context-group purpose="location"><context context-type="linenumber">40</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">59</context></context-group>
</trans-unit>
- <trans-unit id="_msg946">
+ <trans-unit id="_msg965">
<source xml:space="preserve">Error: Dumpfile format record is incorrect. Got &quot;%s&quot;, expected &quot;format&quot;.</source>
- <context-group purpose="location"><context context-type="linenumber">43</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">65</context></context-group>
</trans-unit>
- <trans-unit id="_msg947">
+ <trans-unit id="_msg966">
<source xml:space="preserve">Error: Dumpfile identifier record is incorrect. Got &quot;%s&quot;, expected &quot;%s&quot;.</source>
- <context-group purpose="location"><context context-type="linenumber">45</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">67</context></context-group>
</trans-unit>
- <trans-unit id="_msg948">
+ <trans-unit id="_msg967">
<source xml:space="preserve">Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
- <context-group purpose="location"><context context-type="linenumber">47</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">69</context></context-group>
</trans-unit>
- <trans-unit id="_msg949">
+ <trans-unit id="_msg968">
<source xml:space="preserve">Error: Legacy wallets only support the &quot;legacy&quot;, &quot;p2sh-segwit&quot;, and &quot;bech32&quot; address types</source>
- <context-group purpose="location"><context context-type="linenumber">50</context></context-group>
- </trans-unit>
- <trans-unit id="_msg950">
- <source xml:space="preserve">Error: Listening for incoming connections failed (listen returned error %s)</source>
- <context-group purpose="location"><context context-type="linenumber">53</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">75</context></context-group>
</trans-unit>
- <trans-unit id="_msg951">
+ <trans-unit id="_msg969">
<source xml:space="preserve">Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
- <context-group purpose="location"><context context-type="linenumber">55</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">87</context></context-group>
</trans-unit>
- <trans-unit id="_msg952">
+ <trans-unit id="_msg970">
<source xml:space="preserve">File %s already exists. If you are sure this is what you want, move it out of the way first.</source>
- <context-group purpose="location"><context context-type="linenumber">58</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
</trans-unit>
- <trans-unit id="_msg953">
+ <trans-unit id="_msg971">
<source xml:space="preserve">Invalid amount for -maxtxfee=&lt;amount&gt;: &apos;%s&apos; (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
- <context-group purpose="location"><context context-type="linenumber">61</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
</trans-unit>
- <trans-unit id="_msg954">
+ <trans-unit id="_msg972">
<source xml:space="preserve">Invalid or corrupt peers.dat (%s). If you believe this is a bug, please report it to %s. As a workaround, you can move the file (%s) out of the way (rename, move, or delete) to have a new one created on the next start.</source>
- <context-group purpose="location"><context context-type="linenumber">64</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">99</context></context-group>
</trans-unit>
- <trans-unit id="_msg955">
+ <trans-unit id="_msg973">
<source xml:space="preserve">More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
- <context-group purpose="location"><context context-type="linenumber">68</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">103</context></context-group>
</trans-unit>
- <trans-unit id="_msg956">
+ <trans-unit id="_msg974">
<source xml:space="preserve">No dump file provided. To use createfromdump, -dumpfile=&lt;filename&gt; must be provided.</source>
- <context-group purpose="location"><context context-type="linenumber">71</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">106</context></context-group>
</trans-unit>
- <trans-unit id="_msg957">
+ <trans-unit id="_msg975">
<source xml:space="preserve">No dump file provided. To use dump, -dumpfile=&lt;filename&gt; must be provided.</source>
- <context-group purpose="location"><context context-type="linenumber">74</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">109</context></context-group>
</trans-unit>
- <trans-unit id="_msg958">
+ <trans-unit id="_msg976">
<source xml:space="preserve">No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
- <context-group purpose="location"><context context-type="linenumber">76</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">111</context></context-group>
</trans-unit>
- <trans-unit id="_msg959">
+ <trans-unit id="_msg977">
<source xml:space="preserve">Please check that your computer&apos;s date and time are correct! If your clock is wrong, %s will not work properly.</source>
- <context-group purpose="location"><context context-type="linenumber">79</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">121</context></context-group>
</trans-unit>
- <trans-unit id="_msg960">
+ <trans-unit id="_msg978">
<source xml:space="preserve">Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <context-group purpose="location"><context context-type="linenumber">82</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">124</context></context-group>
</trans-unit>
- <trans-unit id="_msg961">
+ <trans-unit id="_msg979">
<source xml:space="preserve">Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <context-group purpose="location"><context context-type="linenumber">85</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">127</context></context-group>
</trans-unit>
- <trans-unit id="_msg962">
+ <trans-unit id="_msg980">
+ <source xml:space="preserve">Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <context-group purpose="location"><context context-type="linenumber">129</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg981">
<source xml:space="preserve">Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
- <context-group purpose="location"><context context-type="linenumber">87</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">132</context></context-group>
</trans-unit>
- <trans-unit id="_msg963">
+ <trans-unit id="_msg982">
<source xml:space="preserve">SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
- <context-group purpose="location"><context context-type="linenumber">90</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">135</context></context-group>
</trans-unit>
- <trans-unit id="_msg964">
+ <trans-unit id="_msg983">
<source xml:space="preserve">The block database contains a block which appears to be from the future. This may be due to your computer&apos;s date and time being set incorrectly. Only rebuild the block database if you are sure that your computer&apos;s date and time are correct</source>
- <context-group purpose="location"><context context-type="linenumber">96</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">141</context></context-group>
</trans-unit>
- <trans-unit id="_msg965">
+ <trans-unit id="_msg984">
<source xml:space="preserve">The block index db contains a legacy &apos;txindex&apos;. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
- <context-group purpose="location"><context context-type="linenumber">101</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">146</context></context-group>
</trans-unit>
- <trans-unit id="_msg966">
+ <trans-unit id="_msg985">
<source xml:space="preserve">The transaction amount is too small to send after the fee has been deducted</source>
- <context-group purpose="location"><context context-type="linenumber">105</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">150</context></context-group>
</trans-unit>
- <trans-unit id="_msg967">
+ <trans-unit id="_msg986">
<source xml:space="preserve">This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet</source>
- <context-group purpose="location"><context context-type="linenumber">107</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">152</context></context-group>
</trans-unit>
- <trans-unit id="_msg968">
+ <trans-unit id="_msg987">
<source xml:space="preserve">This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
- <context-group purpose="location"><context context-type="linenumber">111</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">156</context></context-group>
</trans-unit>
- <trans-unit id="_msg969">
+ <trans-unit id="_msg988">
<source xml:space="preserve">This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
- <context-group purpose="location"><context context-type="linenumber">114</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">159</context></context-group>
</trans-unit>
- <trans-unit id="_msg970">
+ <trans-unit id="_msg989">
<source xml:space="preserve">This is the transaction fee you may discard if change is smaller than dust at this level</source>
- <context-group purpose="location"><context context-type="linenumber">117</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">162</context></context-group>
</trans-unit>
- <trans-unit id="_msg971">
+ <trans-unit id="_msg990">
<source xml:space="preserve">This is the transaction fee you may pay when fee estimates are not available.</source>
- <context-group purpose="location"><context context-type="linenumber">120</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">165</context></context-group>
</trans-unit>
- <trans-unit id="_msg972">
+ <trans-unit id="_msg991">
<source xml:space="preserve">Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
- <context-group purpose="location"><context context-type="linenumber">122</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">167</context></context-group>
</trans-unit>
- <trans-unit id="_msg973">
+ <trans-unit id="_msg992">
<source xml:space="preserve">Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <context-group purpose="location"><context context-type="linenumber">125</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
</trans-unit>
- <trans-unit id="_msg974">
+ <trans-unit id="_msg993">
<source xml:space="preserve">Unknown wallet file format &quot;%s&quot; provided. Please provide one of &quot;bdb&quot; or &quot;sqlite&quot;.</source>
- <context-group purpose="location"><context context-type="linenumber">128</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
</trans-unit>
- <trans-unit id="_msg975">
+ <trans-unit id="_msg994">
+ <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">184</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg995">
+ <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">187</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg996">
<source xml:space="preserve">Warning: Dumpfile wallet format &quot;%s&quot; does not match command line specified format &quot;%s&quot;.</source>
- <context-group purpose="location"><context context-type="linenumber">131</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">191</context></context-group>
</trans-unit>
- <trans-unit id="_msg976">
+ <trans-unit id="_msg997">
<source xml:space="preserve">Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <context-group purpose="location"><context context-type="linenumber">134</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
</trans-unit>
- <trans-unit id="_msg977">
+ <trans-unit id="_msg998">
<source xml:space="preserve">Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
- <context-group purpose="location"><context context-type="linenumber">136</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
</trans-unit>
- <trans-unit id="_msg978">
+ <trans-unit id="_msg999">
<source xml:space="preserve">Witness data for blocks after height %d requires validation. Please restart with -reindex.</source>
- <context-group purpose="location"><context context-type="linenumber">139</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
</trans-unit>
- <trans-unit id="_msg979">
+ <trans-unit id="_msg1000">
<source xml:space="preserve">You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
- <context-group purpose="location"><context context-type="linenumber">142</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">202</context></context-group>
</trans-unit>
- <trans-unit id="_msg980">
+ <trans-unit id="_msg1001">
<source xml:space="preserve">%s is set very high!</source>
- <context-group purpose="location"><context context-type="linenumber">145</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">211</context></context-group>
</trans-unit>
- <trans-unit id="_msg981">
+ <trans-unit id="_msg1002">
<source xml:space="preserve">-maxmempool must be at least %d MB</source>
- <context-group purpose="location"><context context-type="linenumber">146</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">212</context></context-group>
</trans-unit>
- <trans-unit id="_msg982">
+ <trans-unit id="_msg1003">
<source xml:space="preserve">A fatal internal error occurred, see debug.log for details</source>
- <context-group purpose="location"><context context-type="linenumber">147</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">213</context></context-group>
</trans-unit>
- <trans-unit id="_msg983">
+ <trans-unit id="_msg1004">
<source xml:space="preserve">Cannot resolve -%s address: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">148</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">214</context></context-group>
</trans-unit>
- <trans-unit id="_msg984">
+ <trans-unit id="_msg1005">
<source xml:space="preserve">Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
- <context-group purpose="location"><context context-type="linenumber">149</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">215</context></context-group>
</trans-unit>
- <trans-unit id="_msg985">
+ <trans-unit id="_msg1006">
<source xml:space="preserve">Cannot set -peerblockfilters without -blockfilterindex.</source>
- <context-group purpose="location"><context context-type="linenumber">150</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">216</context></context-group>
</trans-unit>
- <trans-unit id="_msg986">
+ <trans-unit id="_msg1007">
<source xml:space="preserve">Cannot write to data directory &apos;%s&apos;; check permissions.</source>
- <context-group purpose="location"><context context-type="linenumber">151</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">217</context></context-group>
</trans-unit>
- <trans-unit id="_msg987">
+ <trans-unit id="_msg1008">
<source xml:space="preserve">The -txindex upgrade started by a previous version cannot be completed. Restart with the previous version or run a full -reindex.</source>
- <context-group purpose="location"><context context-type="linenumber">93</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">138</context></context-group>
</trans-unit>
- <trans-unit id="_msg988">
+ <trans-unit id="_msg1009">
+ <source xml:space="preserve">%s request to listen on port %u. This port is considered &quot;bad&quot; and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <context-group purpose="location"><context context-type="linenumber">16</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1010">
+ <source xml:space="preserve">-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <context-group purpose="location"><context context-type="linenumber">23</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1011">
+ <source xml:space="preserve">-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <context-group purpose="location"><context context-type="linenumber">27</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1012">
+ <source xml:space="preserve">-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <context-group purpose="location"><context context-type="linenumber">31</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1013">
+ <source xml:space="preserve">Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <context-group purpose="location"><context context-type="linenumber">35</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1014">
<source xml:space="preserve">Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
- <context-group purpose="location"><context context-type="linenumber">24</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">43</context></context-group>
</trans-unit>
- <trans-unit id="_msg989">
+ <trans-unit id="_msg1015">
<source xml:space="preserve">Error loading %s: External signer wallet being loaded without external signer support compiled</source>
- <context-group purpose="location"><context context-type="linenumber">34</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">53</context></context-group>
</trans-unit>
- <trans-unit id="_msg990">
+ <trans-unit id="_msg1016">
+ <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">62</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1017">
+ <source xml:space="preserve">Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <context-group purpose="location"><context context-type="linenumber">72</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1018">
+ <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">78</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1019">
+ <source xml:space="preserve">Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <context-group purpose="location"><context context-type="linenumber">81</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1020">
+ <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">84</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1021">
+ <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">93</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1022">
+ <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">114</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1023">
+ <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">117</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1024">
+ <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">176</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1025">
+ <source xml:space="preserve">Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <context-group purpose="location"><context context-type="linenumber">181</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1026">
+ <source xml:space="preserve">
+Unable to cleanup failed migration</source>
+ <context-group purpose="location"><context context-type="linenumber">205</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1027">
+ <source xml:space="preserve">
+Unable to restore backup of wallet.</source>
+ <context-group purpose="location"><context context-type="linenumber">208</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1028">
<source xml:space="preserve">Config setting for %s only applied on %s network when in [%s] section.</source>
- <context-group purpose="location"><context context-type="linenumber">152</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">218</context></context-group>
</trans-unit>
- <trans-unit id="_msg991">
+ <trans-unit id="_msg1029">
<source xml:space="preserve">Copyright (C) %i-%i</source>
- <context-group purpose="location"><context context-type="linenumber">153</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">219</context></context-group>
</trans-unit>
- <trans-unit id="_msg992">
+ <trans-unit id="_msg1030">
<source xml:space="preserve">Corrupted block database detected</source>
- <context-group purpose="location"><context context-type="linenumber">154</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">220</context></context-group>
</trans-unit>
- <trans-unit id="_msg993">
+ <trans-unit id="_msg1031">
<source xml:space="preserve">Could not find asmap file %s</source>
- <context-group purpose="location"><context context-type="linenumber">155</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">221</context></context-group>
</trans-unit>
- <trans-unit id="_msg994">
+ <trans-unit id="_msg1032">
<source xml:space="preserve">Could not parse asmap file %s</source>
- <context-group purpose="location"><context context-type="linenumber">156</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">222</context></context-group>
</trans-unit>
- <trans-unit id="_msg995">
+ <trans-unit id="_msg1033">
<source xml:space="preserve">Disk space is too low!</source>
- <context-group purpose="location"><context context-type="linenumber">157</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
</trans-unit>
- <trans-unit id="_msg996">
+ <trans-unit id="_msg1034">
<source xml:space="preserve">Do you want to rebuild the block database now?</source>
- <context-group purpose="location"><context context-type="linenumber">158</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
</trans-unit>
- <trans-unit id="_msg997">
+ <trans-unit id="_msg1035">
<source xml:space="preserve">Done loading</source>
- <context-group purpose="location"><context context-type="linenumber">159</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
</trans-unit>
- <trans-unit id="_msg998">
+ <trans-unit id="_msg1036">
<source xml:space="preserve">Dump file %s does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">160</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">226</context></context-group>
</trans-unit>
- <trans-unit id="_msg999">
+ <trans-unit id="_msg1037">
<source xml:space="preserve">Error creating %s</source>
- <context-group purpose="location"><context context-type="linenumber">161</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">227</context></context-group>
</trans-unit>
- <trans-unit id="_msg1000">
+ <trans-unit id="_msg1038">
<source xml:space="preserve">Error initializing block database</source>
- <context-group purpose="location"><context context-type="linenumber">162</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">228</context></context-group>
</trans-unit>
- <trans-unit id="_msg1001">
+ <trans-unit id="_msg1039">
<source xml:space="preserve">Error initializing wallet database environment %s!</source>
- <context-group purpose="location"><context context-type="linenumber">163</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
</trans-unit>
- <trans-unit id="_msg1002">
+ <trans-unit id="_msg1040">
<source xml:space="preserve">Error loading %s</source>
- <context-group purpose="location"><context context-type="linenumber">164</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">230</context></context-group>
</trans-unit>
- <trans-unit id="_msg1003">
+ <trans-unit id="_msg1041">
<source xml:space="preserve">Error loading %s: Private keys can only be disabled during creation</source>
- <context-group purpose="location"><context context-type="linenumber">165</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">231</context></context-group>
</trans-unit>
- <trans-unit id="_msg1004">
+ <trans-unit id="_msg1042">
<source xml:space="preserve">Error loading %s: Wallet corrupted</source>
- <context-group purpose="location"><context context-type="linenumber">166</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">232</context></context-group>
</trans-unit>
- <trans-unit id="_msg1005">
+ <trans-unit id="_msg1043">
<source xml:space="preserve">Error loading %s: Wallet requires newer version of %s</source>
- <context-group purpose="location"><context context-type="linenumber">167</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">233</context></context-group>
</trans-unit>
- <trans-unit id="_msg1006">
+ <trans-unit id="_msg1044">
<source xml:space="preserve">Error loading block database</source>
- <context-group purpose="location"><context context-type="linenumber">168</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">234</context></context-group>
</trans-unit>
- <trans-unit id="_msg1007">
+ <trans-unit id="_msg1045">
<source xml:space="preserve">Error opening block database</source>
- <context-group purpose="location"><context context-type="linenumber">169</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">235</context></context-group>
</trans-unit>
- <trans-unit id="_msg1008">
+ <trans-unit id="_msg1046">
<source xml:space="preserve">Error reading from database, shutting down.</source>
- <context-group purpose="location"><context context-type="linenumber">170</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">236</context></context-group>
</trans-unit>
- <trans-unit id="_msg1009">
+ <trans-unit id="_msg1047">
<source xml:space="preserve">Error reading next record from wallet database</source>
- <context-group purpose="location"><context context-type="linenumber">171</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">237</context></context-group>
</trans-unit>
- <trans-unit id="_msg1010">
- <source xml:space="preserve">Error upgrading chainstate database</source>
- <context-group purpose="location"><context context-type="linenumber">172</context></context-group>
+ <trans-unit id="_msg1048">
+ <source xml:space="preserve">Error: Could not add watchonly tx to watchonly wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">238</context></context-group>
</trans-unit>
- <trans-unit id="_msg1011">
+ <trans-unit id="_msg1049">
+ <source xml:space="preserve">Error: Could not delete watchonly transactions</source>
+ <context-group purpose="location"><context context-type="linenumber">239</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1050">
<source xml:space="preserve">Error: Couldn&apos;t create cursor into database</source>
- <context-group purpose="location"><context context-type="linenumber">173</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">240</context></context-group>
</trans-unit>
- <trans-unit id="_msg1012">
+ <trans-unit id="_msg1051">
<source xml:space="preserve">Error: Disk space is low for %s</source>
- <context-group purpose="location"><context context-type="linenumber">174</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">241</context></context-group>
</trans-unit>
- <trans-unit id="_msg1013">
+ <trans-unit id="_msg1052">
<source xml:space="preserve">Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
- <context-group purpose="location"><context context-type="linenumber">175</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">242</context></context-group>
</trans-unit>
- <trans-unit id="_msg1014">
+ <trans-unit id="_msg1053">
+ <source xml:space="preserve">Error: Failed to create new watchonly wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">243</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1054">
<source xml:space="preserve">Error: Got key that was not hex: %s</source>
- <context-group purpose="location"><context context-type="linenumber">176</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">244</context></context-group>
</trans-unit>
- <trans-unit id="_msg1015">
+ <trans-unit id="_msg1055">
<source xml:space="preserve">Error: Got value that was not hex: %s</source>
- <context-group purpose="location"><context context-type="linenumber">177</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">245</context></context-group>
</trans-unit>
- <trans-unit id="_msg1016">
+ <trans-unit id="_msg1056">
<source xml:space="preserve">Error: Keypool ran out, please call keypoolrefill first</source>
- <context-group purpose="location"><context context-type="linenumber">178</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
</trans-unit>
- <trans-unit id="_msg1017">
+ <trans-unit id="_msg1057">
<source xml:space="preserve">Error: Missing checksum</source>
- <context-group purpose="location"><context context-type="linenumber">179</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">247</context></context-group>
</trans-unit>
- <trans-unit id="_msg1018">
+ <trans-unit id="_msg1058">
<source xml:space="preserve">Error: No %s addresses available.</source>
- <context-group purpose="location"><context context-type="linenumber">180</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">248</context></context-group>
</trans-unit>
- <trans-unit id="_msg1019">
+ <trans-unit id="_msg1059">
+ <source xml:space="preserve">Error: Not all watchonly txs could be deleted</source>
+ <context-group purpose="location"><context context-type="linenumber">249</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1060">
+ <source xml:space="preserve">Error: This wallet already uses SQLite</source>
+ <context-group purpose="location"><context context-type="linenumber">250</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1061">
+ <source xml:space="preserve">Error: This wallet is already a descriptor wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">251</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1062">
+ <source xml:space="preserve">Error: Unable to begin reading all records in the database</source>
+ <context-group purpose="location"><context context-type="linenumber">252</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1063">
+ <source xml:space="preserve">Error: Unable to make a backup of your wallet</source>
+ <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1064">
<source xml:space="preserve">Error: Unable to parse version %u as a uint32_t</source>
- <context-group purpose="location"><context context-type="linenumber">181</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
</trans-unit>
- <trans-unit id="_msg1020">
+ <trans-unit id="_msg1065">
+ <source xml:space="preserve">Error: Unable to read all records in the database</source>
+ <context-group purpose="location"><context context-type="linenumber">255</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1066">
+ <source xml:space="preserve">Error: Unable to remove watchonly address book data</source>
+ <context-group purpose="location"><context context-type="linenumber">256</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1067">
<source xml:space="preserve">Error: Unable to write record to new wallet</source>
- <context-group purpose="location"><context context-type="linenumber">182</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
</trans-unit>
- <trans-unit id="_msg1021">
+ <trans-unit id="_msg1068">
<source xml:space="preserve">Failed to listen on any port. Use -listen=0 if you want this.</source>
- <context-group purpose="location"><context context-type="linenumber">183</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
</trans-unit>
- <trans-unit id="_msg1022">
+ <trans-unit id="_msg1069">
<source xml:space="preserve">Failed to rescan the wallet during initialization</source>
- <context-group purpose="location"><context context-type="linenumber">184</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">259</context></context-group>
</trans-unit>
- <trans-unit id="_msg1023">
+ <trans-unit id="_msg1070">
<source xml:space="preserve">Failed to verify database</source>
- <context-group purpose="location"><context context-type="linenumber">185</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
</trans-unit>
- <trans-unit id="_msg1024">
+ <trans-unit id="_msg1071">
<source xml:space="preserve">Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
- <context-group purpose="location"><context context-type="linenumber">186</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
</trans-unit>
- <trans-unit id="_msg1025">
+ <trans-unit id="_msg1072">
<source xml:space="preserve">Ignoring duplicate -wallet %s.</source>
- <context-group purpose="location"><context context-type="linenumber">187</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">262</context></context-group>
</trans-unit>
- <trans-unit id="_msg1026">
+ <trans-unit id="_msg1073">
<source xml:space="preserve">Importing…</source>
- <context-group purpose="location"><context context-type="linenumber">188</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">263</context></context-group>
</trans-unit>
- <trans-unit id="_msg1027">
+ <trans-unit id="_msg1074">
<source xml:space="preserve">Incorrect or no genesis block found. Wrong datadir for network?</source>
- <context-group purpose="location"><context context-type="linenumber">189</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">264</context></context-group>
</trans-unit>
- <trans-unit id="_msg1028">
+ <trans-unit id="_msg1075">
<source xml:space="preserve">Initialization sanity check failed. %s is shutting down.</source>
- <context-group purpose="location"><context context-type="linenumber">190</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">265</context></context-group>
</trans-unit>
- <trans-unit id="_msg1029">
+ <trans-unit id="_msg1076">
<source xml:space="preserve">Input not found or already spent</source>
- <context-group purpose="location"><context context-type="linenumber">191</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">266</context></context-group>
</trans-unit>
- <trans-unit id="_msg1030">
+ <trans-unit id="_msg1077">
<source xml:space="preserve">Insufficient funds</source>
- <context-group purpose="location"><context context-type="linenumber">192</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">267</context></context-group>
</trans-unit>
- <trans-unit id="_msg1031">
+ <trans-unit id="_msg1078">
<source xml:space="preserve">Invalid -i2psam address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">193</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">268</context></context-group>
</trans-unit>
- <trans-unit id="_msg1032">
+ <trans-unit id="_msg1079">
<source xml:space="preserve">Invalid -onion address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">194</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">269</context></context-group>
</trans-unit>
- <trans-unit id="_msg1033">
+ <trans-unit id="_msg1080">
<source xml:space="preserve">Invalid -proxy address or hostname: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">195</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">270</context></context-group>
</trans-unit>
- <trans-unit id="_msg1034">
+ <trans-unit id="_msg1081">
<source xml:space="preserve">Invalid P2P permission: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">196</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">271</context></context-group>
</trans-unit>
- <trans-unit id="_msg1035">
+ <trans-unit id="_msg1082">
<source xml:space="preserve">Invalid amount for -%s=&lt;amount&gt;: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">197</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">272</context></context-group>
</trans-unit>
- <trans-unit id="_msg1036">
+ <trans-unit id="_msg1083">
<source xml:space="preserve">Invalid amount for -discardfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">198</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">273</context></context-group>
</trans-unit>
- <trans-unit id="_msg1037">
+ <trans-unit id="_msg1084">
<source xml:space="preserve">Invalid amount for -fallbackfee=&lt;amount&gt;: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">199</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">274</context></context-group>
</trans-unit>
- <trans-unit id="_msg1038">
+ <trans-unit id="_msg1085">
<source xml:space="preserve">Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos; (must be at least %s)</source>
- <context-group purpose="location"><context context-type="linenumber">200</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">275</context></context-group>
</trans-unit>
- <trans-unit id="_msg1039">
+ <trans-unit id="_msg1086">
<source xml:space="preserve">Invalid netmask specified in -whitelist: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">201</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">276</context></context-group>
</trans-unit>
- <trans-unit id="_msg1040">
+ <trans-unit id="_msg1087">
+ <source xml:space="preserve">Listening for incoming connections failed (listen returned error %s)</source>
+ <context-group purpose="location"><context context-type="linenumber">277</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1088">
<source xml:space="preserve">Loading P2P addresses…</source>
- <context-group purpose="location"><context context-type="linenumber">202</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">278</context></context-group>
</trans-unit>
- <trans-unit id="_msg1041">
+ <trans-unit id="_msg1089">
<source xml:space="preserve">Loading banlist…</source>
- <context-group purpose="location"><context context-type="linenumber">203</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">279</context></context-group>
</trans-unit>
- <trans-unit id="_msg1042">
+ <trans-unit id="_msg1090">
<source xml:space="preserve">Loading block index…</source>
- <context-group purpose="location"><context context-type="linenumber">204</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">280</context></context-group>
</trans-unit>
- <trans-unit id="_msg1043">
+ <trans-unit id="_msg1091">
<source xml:space="preserve">Loading wallet…</source>
- <context-group purpose="location"><context context-type="linenumber">205</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">281</context></context-group>
</trans-unit>
- <trans-unit id="_msg1044">
+ <trans-unit id="_msg1092">
<source xml:space="preserve">Missing amount</source>
- <context-group purpose="location"><context context-type="linenumber">206</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">282</context></context-group>
</trans-unit>
- <trans-unit id="_msg1045">
+ <trans-unit id="_msg1093">
<source xml:space="preserve">Missing solving data for estimating transaction size</source>
- <context-group purpose="location"><context context-type="linenumber">207</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">283</context></context-group>
</trans-unit>
- <trans-unit id="_msg1046">
+ <trans-unit id="_msg1094">
<source xml:space="preserve">Need to specify a port with -whitebind: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">208</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">284</context></context-group>
</trans-unit>
- <trans-unit id="_msg1047">
+ <trans-unit id="_msg1095">
<source xml:space="preserve">No addresses available</source>
- <context-group purpose="location"><context context-type="linenumber">209</context></context-group>
- </trans-unit>
- <trans-unit id="_msg1048">
- <source xml:space="preserve">No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <context-group purpose="location"><context context-type="linenumber">210</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">285</context></context-group>
</trans-unit>
- <trans-unit id="_msg1049">
+ <trans-unit id="_msg1096">
<source xml:space="preserve">Not enough file descriptors available.</source>
- <context-group purpose="location"><context context-type="linenumber">211</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">286</context></context-group>
</trans-unit>
- <trans-unit id="_msg1050">
+ <trans-unit id="_msg1097">
<source xml:space="preserve">Prune cannot be configured with a negative value.</source>
- <context-group purpose="location"><context context-type="linenumber">212</context></context-group>
- </trans-unit>
- <trans-unit id="_msg1051">
- <source xml:space="preserve">Prune mode is incompatible with -coinstatsindex.</source>
- <context-group purpose="location"><context context-type="linenumber">213</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">287</context></context-group>
</trans-unit>
- <trans-unit id="_msg1052">
+ <trans-unit id="_msg1098">
<source xml:space="preserve">Prune mode is incompatible with -txindex.</source>
- <context-group purpose="location"><context context-type="linenumber">214</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">288</context></context-group>
</trans-unit>
- <trans-unit id="_msg1053">
+ <trans-unit id="_msg1099">
<source xml:space="preserve">Pruning blockstore…</source>
- <context-group purpose="location"><context context-type="linenumber">215</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">289</context></context-group>
</trans-unit>
- <trans-unit id="_msg1054">
+ <trans-unit id="_msg1100">
<source xml:space="preserve">Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <context-group purpose="location"><context context-type="linenumber">216</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">290</context></context-group>
</trans-unit>
- <trans-unit id="_msg1055">
+ <trans-unit id="_msg1101">
<source xml:space="preserve">Replaying blocks…</source>
- <context-group purpose="location"><context context-type="linenumber">217</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">291</context></context-group>
</trans-unit>
- <trans-unit id="_msg1056">
+ <trans-unit id="_msg1102">
<source xml:space="preserve">Rescanning…</source>
- <context-group purpose="location"><context context-type="linenumber">218</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">292</context></context-group>
</trans-unit>
- <trans-unit id="_msg1057">
+ <trans-unit id="_msg1103">
<source xml:space="preserve">SQLiteDatabase: Failed to execute statement to verify database: %s</source>
- <context-group purpose="location"><context context-type="linenumber">219</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">293</context></context-group>
</trans-unit>
- <trans-unit id="_msg1058">
+ <trans-unit id="_msg1104">
<source xml:space="preserve">SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
- <context-group purpose="location"><context context-type="linenumber">220</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">294</context></context-group>
</trans-unit>
- <trans-unit id="_msg1059">
+ <trans-unit id="_msg1105">
<source xml:space="preserve">SQLiteDatabase: Failed to read database verification error: %s</source>
- <context-group purpose="location"><context context-type="linenumber">221</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">295</context></context-group>
</trans-unit>
- <trans-unit id="_msg1060">
+ <trans-unit id="_msg1106">
<source xml:space="preserve">SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
- <context-group purpose="location"><context context-type="linenumber">222</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">296</context></context-group>
</trans-unit>
- <trans-unit id="_msg1061">
+ <trans-unit id="_msg1107">
<source xml:space="preserve">Section [%s] is not recognized.</source>
- <context-group purpose="location"><context context-type="linenumber">223</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">297</context></context-group>
</trans-unit>
- <trans-unit id="_msg1062">
+ <trans-unit id="_msg1108">
<source xml:space="preserve">Signing transaction failed</source>
- <context-group purpose="location"><context context-type="linenumber">224</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">298</context></context-group>
</trans-unit>
- <trans-unit id="_msg1063">
+ <trans-unit id="_msg1109">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; does not exist</source>
- <context-group purpose="location"><context context-type="linenumber">225</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">299</context></context-group>
</trans-unit>
- <trans-unit id="_msg1064">
+ <trans-unit id="_msg1110">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; is a relative path</source>
- <context-group purpose="location"><context context-type="linenumber">226</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">300</context></context-group>
</trans-unit>
- <trans-unit id="_msg1065">
+ <trans-unit id="_msg1111">
<source xml:space="preserve">Specified -walletdir &quot;%s&quot; is not a directory</source>
- <context-group purpose="location"><context context-type="linenumber">227</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">301</context></context-group>
</trans-unit>
- <trans-unit id="_msg1066">
+ <trans-unit id="_msg1112">
<source xml:space="preserve">Specified blocks directory &quot;%s&quot; does not exist.</source>
- <context-group purpose="location"><context context-type="linenumber">228</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">302</context></context-group>
</trans-unit>
- <trans-unit id="_msg1067">
+ <trans-unit id="_msg1113">
<source xml:space="preserve">Starting network threads…</source>
- <context-group purpose="location"><context context-type="linenumber">229</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">303</context></context-group>
</trans-unit>
- <trans-unit id="_msg1068">
+ <trans-unit id="_msg1114">
<source xml:space="preserve">The source code is available from %s.</source>
- <context-group purpose="location"><context context-type="linenumber">230</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">304</context></context-group>
</trans-unit>
- <trans-unit id="_msg1069">
+ <trans-unit id="_msg1115">
<source xml:space="preserve">The specified config file %s does not exist</source>
- <context-group purpose="location"><context context-type="linenumber">231</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">305</context></context-group>
</trans-unit>
- <trans-unit id="_msg1070">
+ <trans-unit id="_msg1116">
<source xml:space="preserve">The transaction amount is too small to pay the fee</source>
- <context-group purpose="location"><context context-type="linenumber">232</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">306</context></context-group>
</trans-unit>
- <trans-unit id="_msg1071">
+ <trans-unit id="_msg1117">
<source xml:space="preserve">The wallet will avoid paying less than the minimum relay fee.</source>
- <context-group purpose="location"><context context-type="linenumber">233</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">307</context></context-group>
</trans-unit>
- <trans-unit id="_msg1072">
+ <trans-unit id="_msg1118">
<source xml:space="preserve">This is experimental software.</source>
- <context-group purpose="location"><context context-type="linenumber">234</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">308</context></context-group>
</trans-unit>
- <trans-unit id="_msg1073">
+ <trans-unit id="_msg1119">
<source xml:space="preserve">This is the minimum transaction fee you pay on every transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">235</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">309</context></context-group>
</trans-unit>
- <trans-unit id="_msg1074">
+ <trans-unit id="_msg1120">
<source xml:space="preserve">This is the transaction fee you will pay if you send a transaction.</source>
- <context-group purpose="location"><context context-type="linenumber">236</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">310</context></context-group>
</trans-unit>
- <trans-unit id="_msg1075">
+ <trans-unit id="_msg1121">
<source xml:space="preserve">Transaction amount too small</source>
- <context-group purpose="location"><context context-type="linenumber">237</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">311</context></context-group>
</trans-unit>
- <trans-unit id="_msg1076">
+ <trans-unit id="_msg1122">
<source xml:space="preserve">Transaction amounts must not be negative</source>
- <context-group purpose="location"><context context-type="linenumber">238</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">312</context></context-group>
</trans-unit>
- <trans-unit id="_msg1077">
+ <trans-unit id="_msg1123">
<source xml:space="preserve">Transaction change output index out of range</source>
- <context-group purpose="location"><context context-type="linenumber">239</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">313</context></context-group>
</trans-unit>
- <trans-unit id="_msg1078">
+ <trans-unit id="_msg1124">
<source xml:space="preserve">Transaction has too long of a mempool chain</source>
- <context-group purpose="location"><context context-type="linenumber">240</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">314</context></context-group>
</trans-unit>
- <trans-unit id="_msg1079">
+ <trans-unit id="_msg1125">
<source xml:space="preserve">Transaction must have at least one recipient</source>
- <context-group purpose="location"><context context-type="linenumber">241</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">315</context></context-group>
</trans-unit>
- <trans-unit id="_msg1080">
+ <trans-unit id="_msg1126">
<source xml:space="preserve">Transaction needs a change address, but we can&apos;t generate it.</source>
- <context-group purpose="location"><context context-type="linenumber">242</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">316</context></context-group>
</trans-unit>
- <trans-unit id="_msg1081">
+ <trans-unit id="_msg1127">
<source xml:space="preserve">Transaction too large</source>
- <context-group purpose="location"><context context-type="linenumber">243</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">317</context></context-group>
</trans-unit>
- <trans-unit id="_msg1082">
+ <trans-unit id="_msg1128">
+ <source xml:space="preserve">Unable to allocate memory for -maxsigcachesize: &apos;%s&apos; MiB</source>
+ <context-group purpose="location"><context context-type="linenumber">318</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1129">
<source xml:space="preserve">Unable to bind to %s on this computer (bind returned error %s)</source>
- <context-group purpose="location"><context context-type="linenumber">244</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">319</context></context-group>
</trans-unit>
- <trans-unit id="_msg1083">
+ <trans-unit id="_msg1130">
<source xml:space="preserve">Unable to bind to %s on this computer. %s is probably already running.</source>
- <context-group purpose="location"><context context-type="linenumber">245</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">320</context></context-group>
</trans-unit>
- <trans-unit id="_msg1084">
+ <trans-unit id="_msg1131">
<source xml:space="preserve">Unable to create the PID file &apos;%s&apos;: %s</source>
- <context-group purpose="location"><context context-type="linenumber">246</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">321</context></context-group>
</trans-unit>
- <trans-unit id="_msg1085">
+ <trans-unit id="_msg1132">
+ <source xml:space="preserve">Unable to find UTXO for external input</source>
+ <context-group purpose="location"><context context-type="linenumber">322</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1133">
<source xml:space="preserve">Unable to generate initial keys</source>
- <context-group purpose="location"><context context-type="linenumber">247</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">323</context></context-group>
</trans-unit>
- <trans-unit id="_msg1086">
+ <trans-unit id="_msg1134">
<source xml:space="preserve">Unable to generate keys</source>
- <context-group purpose="location"><context context-type="linenumber">248</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">324</context></context-group>
</trans-unit>
- <trans-unit id="_msg1087">
+ <trans-unit id="_msg1135">
<source xml:space="preserve">Unable to open %s for writing</source>
- <context-group purpose="location"><context context-type="linenumber">249</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">325</context></context-group>
</trans-unit>
- <trans-unit id="_msg1088">
+ <trans-unit id="_msg1136">
<source xml:space="preserve">Unable to parse -maxuploadtarget: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">250</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">326</context></context-group>
</trans-unit>
- <trans-unit id="_msg1089">
+ <trans-unit id="_msg1137">
<source xml:space="preserve">Unable to start HTTP server. See debug log for details.</source>
- <context-group purpose="location"><context context-type="linenumber">251</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">327</context></context-group>
</trans-unit>
- <trans-unit id="_msg1090">
+ <trans-unit id="_msg1138">
+ <source xml:space="preserve">Unable to unload the wallet before migrating</source>
+ <context-group purpose="location"><context context-type="linenumber">328</context></context-group>
+ </trans-unit>
+ <trans-unit id="_msg1139">
<source xml:space="preserve">Unknown -blockfilterindex value %s.</source>
- <context-group purpose="location"><context context-type="linenumber">252</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">329</context></context-group>
</trans-unit>
- <trans-unit id="_msg1091">
+ <trans-unit id="_msg1140">
<source xml:space="preserve">Unknown address type &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">253</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">330</context></context-group>
</trans-unit>
- <trans-unit id="_msg1092">
+ <trans-unit id="_msg1141">
<source xml:space="preserve">Unknown change type &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">254</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">331</context></context-group>
</trans-unit>
- <trans-unit id="_msg1093">
+ <trans-unit id="_msg1142">
<source xml:space="preserve">Unknown network specified in -onlynet: &apos;%s&apos;</source>
- <context-group purpose="location"><context context-type="linenumber">255</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">332</context></context-group>
</trans-unit>
- <trans-unit id="_msg1094">
+ <trans-unit id="_msg1143">
<source xml:space="preserve">Unknown new rules activated (versionbit %i)</source>
- <context-group purpose="location"><context context-type="linenumber">256</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">333</context></context-group>
</trans-unit>
- <trans-unit id="_msg1095">
- <source xml:space="preserve">Unsupported logging category %s=%s.</source>
- <context-group purpose="location"><context context-type="linenumber">257</context></context-group>
+ <trans-unit id="_msg1144">
+ <source xml:space="preserve">Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <context-group purpose="location"><context context-type="linenumber">334</context></context-group>
</trans-unit>
- <trans-unit id="_msg1096">
- <source xml:space="preserve">Upgrading UTXO database</source>
- <context-group purpose="location"><context context-type="linenumber">258</context></context-group>
+ <trans-unit id="_msg1145">
+ <source xml:space="preserve">Unsupported logging category %s=%s.</source>
+ <context-group purpose="location"><context context-type="linenumber">335</context></context-group>
</trans-unit>
- <trans-unit id="_msg1097">
+ <trans-unit id="_msg1146">
<source xml:space="preserve">User Agent comment (%s) contains unsafe characters.</source>
- <context-group purpose="location"><context context-type="linenumber">259</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">336</context></context-group>
</trans-unit>
- <trans-unit id="_msg1098">
+ <trans-unit id="_msg1147">
<source xml:space="preserve">Verifying blocks…</source>
- <context-group purpose="location"><context context-type="linenumber">260</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">337</context></context-group>
</trans-unit>
- <trans-unit id="_msg1099">
+ <trans-unit id="_msg1148">
<source xml:space="preserve">Verifying wallet(s)…</source>
- <context-group purpose="location"><context context-type="linenumber">261</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">338</context></context-group>
</trans-unit>
- <trans-unit id="_msg1100">
+ <trans-unit id="_msg1149">
<source xml:space="preserve">Wallet needed to be rewritten: restart %s to complete</source>
- <context-group purpose="location"><context context-type="linenumber">262</context></context-group>
+ <context-group purpose="location"><context context-type="linenumber">339</context></context-group>
</trans-unit>
</group>
</body></file>
diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts
index 655f3cc84b..fe52d2afb4 100644
--- a/src/qt/locale/bitcoin_eo.ts
+++ b/src/qt/locale/bitcoin_eo.ts
@@ -568,6 +568,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">defaÅ­lta monujo</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Monujo-Nomo</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Fenestro</translation>
</message>
@@ -930,6 +935,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Bitmono</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -1147,6 +1173,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Konfirmi reŝargo de agordoj</translation>
</message>
<message>
@@ -1719,15 +1746,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Tajpu etikedon por tiu ĉi adreso por aldoni Äin al la listo de uzitaj adresoj</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pagi Al:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Memorando:</translation>
- </message>
-</context>
+ </context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -1854,10 +1873,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/nekonfirmite</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 konfirmoj</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts
index 7ccc2c24d9..96fc7bf082 100644
--- a/src/qt/locale/bitcoin_es.ts
+++ b/src/qt/locale/bitcoin_es.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">Haz clic derecho para editar la dirección o etiqueta </translation>
+ <translation type="unfinished">Haz clic con el botón derecho del ratón para editar la dirección o la etiqueta</translation>
</message>
<message>
<source>Create a new address</source>
@@ -23,11 +23,11 @@
</message>
<message>
<source>C&amp;lose</source>
- <translation type="unfinished">Cerrar</translation>
+ <translation type="unfinished">C&amp;errar</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished">Borrar de la lista la dirección seleccionada</translation>
+ <translation type="unfinished">Eliminar de la lista la dirección actualmente seleccionada</translation>
</message>
<message>
<source>Enter address or label to search</source>
@@ -43,7 +43,7 @@
</message>
<message>
<source>&amp;Delete</source>
- <translation type="unfinished">&amp;Borrar</translation>
+ <translation type="unfinished">E&amp;liminar</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
@@ -55,7 +55,7 @@
</message>
<message>
<source>C&amp;hoose</source>
- <translation type="unfinished">Escoger</translation>
+ <translation type="unfinished">E&amp;scoger</translation>
</message>
<message>
<source>Sending addresses</source>
@@ -67,13 +67,13 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation type="unfinished">Estas son tus direcciones Bitcoin para enviar pagos. Comprueba siempre la cantidad y la dirección de recibo antes de transferir monedas.</translation>
+ <translation type="unfinished">Estas son tus direcciones Bitcoin para enviar pagos. Comprueba siempre el importe y la dirección de recepción antes de transferir monedas.</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
Signing is only possible with addresses of the type 'legacy'.</source>
- <translation type="unfinished">Estas son tus direcciones Bitcoin para la recepción de pagos. Usa el botón 'Crear una nueva dirección para recepción' en la pestaña Recibir para crear nuevas direcciones.
-Firmar solo es posible con direcciones del tipo Legacy.</translation>
+ <translation type="unfinished">Estas son tus direcciones Bitcoin para la recepción de pagos. Usa el botón «Crear una nueva dirección para recepción» en la pestaña Recibir para crear nuevas direcciones.
+Firmar solo es posible con direcciones del tipo «Legacy».</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -81,7 +81,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation type="unfinished">Copiar &amp;Etiqueta</translation>
+ <translation type="unfinished">Copiar &amp;etiqueta</translation>
</message>
<message>
<source>&amp;Edit</source>
@@ -89,7 +89,12 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Export Address List</source>
- <translation type="unfinished">Exportar la Lista de Direcciones</translation>
+ <translation type="unfinished">Exportar la lista de direcciones</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Archivo separado por comas</translation>
</message>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
@@ -160,7 +165,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished">Atención: Si cifras tu monedero y pierdes la contraseña, perderás ¡&lt;b&gt;TODOS TUS BITCOINS&lt;/b&gt;!</translation>
+ <translation type="unfinished">Atención: Si cifras tu monedero y pierdes la contraseña, &lt;b&gt;¡PERDERÃS TODOS TUS BITCOINS!&lt;/b&gt;</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -196,7 +201,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation type="unfinished">IMPORTANTE: Cualquier copia de seguridad que hayas hecho del archivo de tu monedero debe ser reemplazada por el archivo cifrado del monedero recién generado. Por razones de seguridad, las copias de seguridad anteriores del archivo de la billetera sin cifrar serán inútiles cuando empieces a usar el nuevo monedero cifrado.</translation>
+ <translation type="unfinished">IMPORTANTE: Cualquier copia de seguridad que hayas hecho del archivo de tu monedero debe ser reemplazada por el archivo cifrado del monedero recién generado. Por razones de seguridad, las copias de seguridad anteriores del archivo del monedero sin cifrar serán inútiles cuando empieces a usar el nuevo monedero cifrado.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
@@ -208,7 +213,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
- <translation type="unfinished">Las contraseñas dadas no coinciden.</translation>
+ <translation type="unfinished">Las contraseñas proporcionadas no coinciden.</translation>
</message>
<message>
<source>Wallet unlock failed</source>
@@ -235,12 +240,16 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Banned Until</source>
- <translation type="unfinished">Prohibido hasta</translation>
+ <translation type="unfinished">Bloqueado hasta</translation>
</message>
</context>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">El archivo de configuración %1 puede estar corrupto o no ser válido.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Excepción fuera de control</translation>
</message>
@@ -267,11 +276,15 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<message>
<source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
<extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
- <translation type="unfinished">Un error fatal ha ocurrido. Comprueba que el archivo de configuración soporta escritura, o intenta correr de nuevo el programa con -nosettings</translation>
+ <translation type="unfinished">Un error fatal ha ocurrido. Comprueba que el archivo de configuración soporta escritura, o intenta ejecutar de nuevo el programa con -nosettings</translation>
</message>
<message>
<source>Error: Specified data directory "%1" does not exist.</source>
- <translation type="unfinished">Error: El directorio de datos especificado "%1" no existe.</translation>
+ <translation type="unfinished">Error: El directorio de datos especificado «%1» no existe.</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation type="unfinished">Error: No se puede analizar/parsear el archivo de configuración: %1.</translation>
</message>
<message>
<source>%1 didn't yet exit safely…</source>
@@ -283,7 +296,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Amount</source>
- <translation type="unfinished">Cantidad</translation>
+ <translation type="unfinished">Importe</translation>
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
@@ -298,6 +311,16 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Interno</translation>
</message>
<message>
+ <source>Inbound</source>
+ <extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
+ <translation type="unfinished">Entrante</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <extracomment>An outbound connection to a peer. An outbound connection is a connection initiated by us.</extracomment>
+ <translation type="unfinished">Saliente</translation>
+ </message>
+ <message>
<source>Full Relay</source>
<extracomment>Peer connection type that relays all network information.</extracomment>
<translation type="unfinished">Transmisión completa</translation>
@@ -328,43 +351,47 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n segundo</numerusform>
+ <numerusform>%n segundos</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n minuto</numerusform>
+ <numerusform>%n minutos</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n hora</numerusform>
+ <numerusform>%n horas</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n día</numerusform>
+ <numerusform>%n días</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n semana</numerusform>
+ <numerusform>%n semanas</numerusform>
</translation>
</message>
+ <message>
+ <source>%1 and %2</source>
+ <translation type="unfinished">%1 y %2</translation>
+ </message>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n años</numerusform>
+ <numerusform>%n años</numerusform>
</translation>
</message>
</context>
@@ -379,44 +406,76 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">El archivo de configuración no puede escribirse</translation>
</message>
<message>
+ <source>The %s developers</source>
+ <translation type="unfinished">Los desarrolladores de %s</translation>
+ </message>
+ <message>
<source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
<translation type="unfinished">%s corrupto. Intenta utilizar la herramienta del monedero bitcoin-monedero para salvar o restaurar una copia de seguridad.</translation>
</message>
<message>
+ <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
+ <translation type="unfinished">-maxtxfee tiene un valor muy elevado! Comisiones muy grandes podrían ser pagadas en una única transacción.</translation>
+ </message>
+ <message>
<source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
<translation type="unfinished">No se pudo cambiar la versión %i a la versión anterior %i. Versión del monedero sin cambios.</translation>
</message>
<message>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation type="unfinished">No se puede bloquear el directorio %s. %s probablemente ya se está ejecutando.</translation>
+ </message>
+ <message>
<source>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>
- <translation type="unfinished">No se puede actualizar un monedero no dividido en HD de la versión 1%i a la versión 1%i sin actualizar para admitir el grupo de claves pre-dividido. Por favor, use la versión 1%i o ninguna versión especificada.</translation>
+ <translation type="unfinished">No se puede actualizar un monedero no dividido en HD de la versión %i a la versión %i sin actualizar para admitir el grupo de claves pre-dividido. Por favor, use la versión %i o ninguna versión especificada.</translation>
+ </message>
+ <message>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation type="unfinished">Distribuido bajo la licencia de software MIT, vea el archivo adjunto %s o %s</translation>
+ </message>
+ <message>
+ <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation type="unfinished">¡Error leyendo %s!. Todas las claves se han leído correctamente, pero los datos de la transacción o el libro de direcciones pueden faltar o ser incorrectos.</translation>
</message>
<message>
<source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
- <translation type="unfinished">¡Error de lectura %s! Los datos de la transacción pueden faltar o ser incorrectos. Reescaneo de la billetera.</translation>
+ <translation type="unfinished">¡Error de lectura %s! Los datos de la transacción pueden faltar o ser incorrectos. Reescaneo del monedero.</translation>
</message>
<message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
- <translation type="unfinished">Error: el registro del formato del archivo de volcado es incorrecto. Se obtuvo "%s", del "formato" esperado.</translation>
+ <translation type="unfinished">Error: el registro del formato del archivo de volcado es incorrecto. Se obtuvo «%s», del «formato» esperado.</translation>
</message>
<message>
<source>Error: Dumpfile identifier record is incorrect. Got "%s", expected "%s".</source>
- <translation type="unfinished">Error: el registro del identificador del archivo de volcado es incorrecto. Se obtuvo "%s" se esperaba "%s".</translation>
+ <translation type="unfinished">Error: el registro del identificador del archivo de volcado es incorrecto. Se obtuvo «%s» se esperaba «%s».</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
+ <translation type="unfinished">Error: la versión del archivo volcado no es compatible. Esta versión de monedero bitcoin solo admite archivos de volcado de la versión 1. Consigue volcado de fichero con la versión %s</translation>
</message>
<message>
<source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
- <translation type="unfinished">Error: Los monederos heredados solo admiten los tipos de dirección "legacy", "p2sh-segwit" y "bech32"</translation>
+ <translation type="unfinished">Error: Los monederos heredados solo admiten los tipos de dirección «legacy», «p2sh-segwit» y «bech32»</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation type="unfinished">Estimación de la comisión fallida. Fallbackfee está deshabilitado. Espere unos pocos bloques o habilite -fallbackfee.</translation>
</message>
<message>
<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">El archivo %s ya existe. Si está seguro de que esto es lo que quiere, muévalo de lugar primero.</translation>
</message>
<message>
+ <source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
+ <translation type="unfinished">Importe inválido para -maxtxfee=&lt;amount&gt;: «%s» (debe ser al menos la comisión mímina de %s para prevenir transacciones atascadas)</translation>
+ </message>
+ <message>
<source>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>
- <translation type="unfinished">Peers.dat inválido o corrupto (%s). Si cree que se trata de un error, infórmelo a %s. Como alternativa, puedes mover el archivo (%s) (renombrarlo, moverlo o eliminarlo) para que se cree uno nuevo en el siguiente inicio.</translation>
+ <translation type="unfinished">Archivo peers.dat inválido o corrupto (%s). Si cree que se trata de un error, infórmelo a %s. Como alternativa, puedes mover el archivo (%s) (renombrarlo, moverlo o eliminarlo) para que se cree uno nuevo en el siguiente inicio.</translation>
</message>
<message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
- <translation type="unfinished">Se proporciona más de una dirección de ligar de cebolla. Utilizando %s para el servicio Tor cebolla creado automático.</translation>
+ <translation type="unfinished">Se proporciona más de una dirección de enlace onion. Utilizando %s para el servicio onion de Tor creado automáticamente.</translation>
</message>
<message>
<source>No dump file provided. To use createfromdump, -dumpfile=&lt;filename&gt; must be provided.</source>
@@ -428,41 +487,121 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
- <translation type="unfinished">Ningún archivo de billetera proveído. Para usar createfromdump, -format=&lt;format&gt;debe ser proveído.</translation>
+ <translation type="unfinished">Ningún archivo de formato monedero facilitado. Para usar createfromdump, -format=&lt;format&gt;debe ser facilitado.</translation>
+ </message>
+ <message>
+ <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
+ <translation type="unfinished">¡Por favor, compruebe si la fecha y hora en su computadora son correctas! Si su reloj está mal, %s no trabajará correctamente.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation type="unfinished">Contribuya si encuentra %s de utilidad. Visite %s para más información acerca del programa.</translation>
+ </message>
+ <message>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation type="unfinished">La poda se ha configurado por debajo del mínimo de %d MiB. Por favor utiliza un valor mas alto.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">El modo poda no es compatible con -reindex-chainstate. Haz uso de un -reindex completo en su lugar.</translation>
+ </message>
+ <message>
+ <source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
+ <translation type="unfinished">Poda: la última sincronización del monedero sobrepasa los datos podados. Necesita reindexar con -reindex (o descargar la cadena de bloques de nuevo en el caso de un nodo podado)</translation>
</message>
<message>
<source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
<translation type="unfinished">SQLiteDatabase: versión del esquema de la monedero sqlite desconocido %d. Sólo version %d se admite</translation>
</message>
<message>
+ <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
+ <translation type="unfinished">La base de datos de bloques contiene un bloque que parece ser del futuro. Esto puede ser porque la fecha y hora de su ordenador están mal ajustados. Reconstruya la base de datos de bloques solo si está seguro de que la fecha y hora de su ordenador están ajustadas correctamente.</translation>
+ </message>
+ <message>
<source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
- <translation type="unfinished">El índice de bloque db contiene un 'txindex' heredado. Para borrar el espacio de disco ocupado, ejecute un -reindex completo, de lo contrario ignore este error. Este mensaje de error no se volverá a mostrar.</translation>
+ <translation type="unfinished">El índice de bloque db contiene un «txindex» heredado. Para borrar el espacio de disco ocupado, ejecute un -reindex completo, de lo contrario ignore este error. Este mensaje de error no se volverá a mostrar.</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation type="unfinished">Importe de transacción muy pequeño después de la deducción de la comisión</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">Este error podría ocurrir si la billetera no fuese apagada correctamente y fuese cargada usando una compilación con una versión más nueva de Berkeley DB. Si es así, utilice el software que cargó por última vez en esta billetera.</translation>
+ <translation type="unfinished">Este error podría ocurrir si el monedero no fuese apagado correctamente y fuese cargado usando una compilación con una versión más nueva de Berkeley DB. Si es así, utilice el software que cargó por última vez este monedero.</translation>
+ </message>
+ <message>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation type="unfinished">Esta es una versión de pre-prueba - utilícela bajo su propio riesgo. No la utilice para usos comerciales o de minería.</translation>
</message>
<message>
<source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
- <translation type="unfinished">Esta es la tarifa máxima que pagas (además de la tarifa normal) para priorizar la evasión del gasto parcial sobre la selección regular de monedas.</translation>
+ <translation type="unfinished">Esta es la comisión máxima que pagas (además de la comisión normal) para priorizar la evasión del gasto parcial sobre la selección regular de monedas.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation type="unfinished">Esta es la comisión de transacción que puede descartar si el cambio es más pequeño que el polvo a este nivel.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation type="unfinished">Esta es la comisión por transacción que deberá pagar cuando la estimación de comisión no esté disponible.</translation>
+ </message>
+ <message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation type="unfinished">La longitud total de la cadena de versión de red ( %i ) supera la longitud máxima ( %i ) . Reducir el número o tamaño de uacomments .</translation>
+ </message>
+ <message>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation type="unfinished">No se ha podido reproducir los bloques. Deberá reconstruir la base de datos utilizando -reindex-chainstate.</translation>
</message>
<message>
<source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
- <translation type="unfinished">Formato de monedero desconocido "%s" proporcionado. Por favor, proporcione uno de "bdb" o "sqlite".</translation>
+ <translation type="unfinished">Formato de monedero desconocido «%s» proporcionado. Por favor, proporcione uno de «bdb» o «sqlite».</translation>
+ </message>
+ <message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Formato de la base de datos chainstate encontrado. Por favor reinicia con -reindex-chainstate. Esto reconstruirá la base de datos chainstate.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Monedero creado satisfactoriamente. El tipo de monedero «Legacy» está descontinuado y la asistencia para crear y abrir monederos «legacy» será eliminada en el futuro.</translation>
</message>
<message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
- <translation type="unfinished">Aviso: el formato del monedero del archivo de volcado "%s" no coincide con el formato especificado en la línea de comandos "%s".</translation>
+ <translation type="unfinished">Aviso: el formato del monedero del archivo de volcado «%s» no coincide con el formato especificado en la línea de comandos «%s».</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation type="unfinished">Advertencia: Claves privadas detectadas en el monedero {%s} con clave privada deshabilitada</translation>
+ </message>
+ <message>
+ <source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
+ <translation type="unfinished">Advertencia: ¡No parecemos concordar del todo con nuestros pares! Puede que necesite actualizarse, o puede que otros nodos necesiten actualizarse.</translation>
</message>
<message>
<source>Witness data for blocks after height %d requires validation. Please restart with -reindex.</source>
<translation type="unfinished">Hay que validar los datos de los testigos de los bloques después de la altura%d. Por favor, reinicie con -reindex.</translation>
</message>
<message>
+ <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
+ <translation type="unfinished">Necesita reconstruir la base de datos utilizando -reindex para volver al modo sin poda. Esto volverá a descargar toda la cadena de bloques</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation type="unfinished">¡%s esta configurado muy alto!</translation>
+ </message>
+ <message>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation type="unfinished">-maxmempool debe ser por lo menos de %d MB</translation>
+ </message>
+ <message>
<source>A fatal internal error occurred, see debug.log for details</source>
<translation type="unfinished">Ha ocurrido un error interno grave. Consulta debug.log para más detalles.</translation>
</message>
<message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation type="unfinished">No se puede resolver -%s dirección: «%s»</translation>
+ </message>
+ <message>
<source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
<translation type="unfinished">No se puede establecer -forcednsseed a true cuando se establece -dnsseed a false.</translation>
</message>
@@ -471,10 +610,130 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">No se puede establecer -peerblockfilters sin -blockfilterindex.</translation>
</message>
<message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation type="unfinished">No es posible escribir en el directorio «%s»; comprueba permisos.</translation>
+ </message>
+ <message>
+ <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">La actualización -txindex iniciada por una versión anterior no puede completarse. Reinicie con la versión anterior o ejecute un -reindex completo.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">solicitud %s de escucha en el puerto %u . Este puerto se considera "malo" y por lo tanto es poco probable que ningún par de Bitcoin Core se conecte a él. Ver doc/p2p-bad-ports.md para más detalles y una lista completa.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">La opción -reindex-chainstate no es compatible con -blockfilterindex. Por favor, desactiva temporalmente blockfilterindex cuando uses -reindex-chainstate, o sustituye -reindex-chainstate por -reindex para reconstruir completamente todos los índices.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">La opción -reindex-chainstate no es compatible con -coinstatsindex. Por favor, desactiva temporalmente coinstatsindex cuando uses -reindex-chainstate, o sustituye -reindex-chainstate por -reindex para reconstruir completamente todos los índices.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">La opción -reindex-chainstate no es compatible con -txindex. Por favor, desactiva temporalmente txindex cuando uses -reindex-chainstate, o sustituye -reindex-chainstate por -reindex para reconstruir completamente todos los índices.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Asumido-válido: la última sincronización del monedero va más allá de los datos de bloques disponibles. Debes esperar a que se descarguen en segundo plano más bloques de la cadena de validación.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">No se puede proporcionar conexiones específicas y hacer que addrman encuentre conexiones salientes al mismo tiempo.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Error de carga %s : Se está cargando el monedero del firmante externo sin que se haya compilado el soporte del firmante externo</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Error: los datos de la libreta de direcciones en el monedero no se identifican como pertenecientes a monederos migrados</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">Error: Se han creado descriptores duplicados durante la migración. Tu monedero puede estar dañado.</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Error: La transacción %s del monedero no se puede identificar como perteneciente a monederos migrados</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">Error: No se pueden producir descriptores para este monedero legacy. Asegúrate primero que el monedero está desbloqueado.</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">No se ha podido cambiar el nombre del archivo peers.dat . Por favor, muévalo o elimínelo e inténtelo de nuevo.</translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">Opciones incompatibles: -dnsseed=1 se especificó explicitamente, pero -onlynet impide conexiones a IPv4/IPv6</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">Conexiones salientes restringidas a Tor (-onlynet=onion) pero el proxy para alcanzar la red Tor está explícitamente prohibido: -onion=0</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Conexiones salientes restringidas a Tor (-onlynet=onion) pero no se proporciona el proxy para alcanzar la red Tor: no se indica ninguna de las opciones -proxy, -onion, o -listenonion </translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">Se encontró un descriptor desconocido. Cargando monedero %s
+
+El monedero puede haber sido creado con una versión más nueva.
+Por favor intenta ejecutar la ultima versión del software.
+</translation>
+ </message>
+ <message>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished">Categoría especifica de nivel de registro no soportada -loglevel=%s. Se espera -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Categorías válidas: %s. Niveles de registro válidos: %s.</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+No es posible limpiar la migración fallida</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+No es posible restaurar la copia de seguridad del monedero.</translation>
+ </message>
+ <message>
+ <source>Config setting for %s only applied on %s network when in [%s] section.</source>
+ <translation type="unfinished">Los ajustes de configuración para %s solo aplicados en la red %s cuando se encuentra en la sección [%s].</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation type="unfinished">Corrupción de base de datos de bloques detectada.</translation>
+ </message>
+ <message>
+ <source>Could not find asmap file %s</source>
+ <translation type="unfinished">No se pudo encontrar el archivo AS Map %s</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation type="unfinished">No se pudo analizar el archivo AS Map %s</translation>
+ </message>
+ <message>
<source>Disk space is too low!</source>
<translation type="unfinished">¡El espacio en el disco es demasiado pequeño!</translation>
</message>
<message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation type="unfinished">¿Quieres reconstruir la base de datos de bloques ahora?</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation type="unfinished">Carga completa</translation>
+ </message>
+ <message>
<source>Dump file %s does not exist.</source>
<translation type="unfinished">El archivo de volcado %s no existe</translation>
</message>
@@ -483,20 +742,72 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Error creando %s</translation>
</message>
<message>
+ <source>Error initializing block database</source>
+ <translation type="unfinished">Error al inicializar la base de datos de bloques</translation>
+ </message>
+ <message>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation type="unfinished">Error al inicializar el entorno de la base de datos del monedero %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation type="unfinished">Error cargando %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation type="unfinished">Error cargando %s: Las claves privadas solo pueden ser deshabilitadas durante la creación.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation type="unfinished">Error cargando %s: Monedero corrupto</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation type="unfinished">Error cargando %s: Monedero requiere una versión mas reciente de %s</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation type="unfinished">Error cargando base de datos de bloques</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation type="unfinished">Error al abrir base de datos de bloques.</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation type="unfinished">Error al leer la base de datos, cerrando aplicación.</translation>
+ </message>
+ <message>
<source>Error reading next record from wallet database</source>
- <translation type="unfinished">Error al leer el seguiente registro de la base de datos de la "wallet"</translation>
+ <translation type="unfinished">Error al leer el siguiente registro de la base de datos del monedero</translation>
+ </message>
+ <message>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">Error: No se puede añadir la transacción de observación al monedero de observación</translation>
+ </message>
+ <message>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">Error: No se pueden eliminar las transacciones de observación</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Error: No se pudo crear el cursor en la base de datos</translation>
</message>
<message>
+ <source>Error: Disk space is low for %s</source>
+ <translation type="unfinished">Error: Espacio en disco bajo por %s</translation>
+ </message>
+ <message>
<source>Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
<translation type="unfinished">Error: La suma de comprobación del archivo de volcado no coincide. Calculada%s, prevista%s</translation>
</message>
<message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">Error: No se puede crear un monedero de observación</translation>
+ </message>
+ <message>
<source>Error: Got key that was not hex: %s</source>
- <translation type="unfinished">Error: Se recibió una llave que no es hex: %s</translation>
+ <translation type="unfinished">Error: Se recibió una clave que no es hex: %s</translation>
</message>
<message>
<source>Error: Got value that was not hex: %s</source>
@@ -504,24 +815,59 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Error: Keypool ran out, please call keypoolrefill first</source>
- <translation type="unfinished">Keypool se ha agotado, por favor, llama a keypoolrefill antes</translation>
+ <translation type="unfinished">Error: Keypool se ha agotado, por favor, invoca «keypoolrefill» primero</translation>
</message>
<message>
<source>Error: Missing checksum</source>
- <translation type="unfinished">Error: No se ha encontrado 'checksum'</translation>
+ <translation type="unfinished">Error: No se ha encontrado suma de comprobación</translation>
</message>
<message>
<source>Error: No %s addresses available.</source>
- <translation type="unfinished">Error: No hay %sdirecciones disponibles.
-</translation>
+ <translation type="unfinished">Error: No hay direcciones %s disponibles .</translation>
+ </message>
+ <message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">Error: No se pueden eliminar todas las transacciones de observación</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Error: Este monedero ya usa SQLite</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">Error: Este monedero ya es un monedero descriptor</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">Error: No es posible comenzar a leer todos los registros en la base de datos</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Error: No es posible realizar la copia de seguridad de tu monedero</translation>
</message>
<message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">Error: No se ha podido analizar la versión %ucomo uint32_t</translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Error: No es posible leer todos los registros en la base de datos</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">Error: No es posible eliminar los datos de la libreta de direcciones de observación</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
- <translation type="unfinished">Error: No se pudo escribir el registro en la nueva billetera</translation>
+ <translation type="unfinished">Error: No se pudo escribir el registro en el nuevo monedero</translation>
+ </message>
+ <message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation type="unfinished">Ha fallado la escucha en todos los puertos. Usa -listen=0 si deseas esto.</translation>
+ </message>
+ <message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation type="unfinished">Fallo al volver a escanear el monedero durante el inicio</translation>
</message>
<message>
<source>Failed to verify database</source>
@@ -540,6 +886,14 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Importando...</translation>
</message>
<message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation type="unfinished">Bloque de génesis no encontrado o incorrecto. ¿datadir equivocada para la red?</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation type="unfinished">La inicialización de la verificación de validez falló. Se está cerrando %s.</translation>
+ </message>
+ <message>
<source>Input not found or already spent</source>
<translation type="unfinished">Entrada no encontrada o ya gastada</translation>
</message>
@@ -549,7 +903,43 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Invalid -i2psam address or hostname: '%s'</source>
- <translation type="unfinished">Dirección de -i2psam o dominio ' %s' inválido</translation>
+ <translation type="unfinished">Dirección de -i2psam o dominio «%s» inválido</translation>
+ </message>
+ <message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation type="unfinished">Dirección -onion o hostname: «%s» inválido</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation type="unfinished">Dirección -proxy o hostname: «%s» inválido</translation>
+ </message>
+ <message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation type="unfinished">Permiso P2P: «%s» inválido</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation type="unfinished">Importe para -%s=&lt;amount&gt;: «%s» inválido</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation type="unfinished">Importe para -discardfee=&lt;amount&gt;: «%s» inválido</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation type="unfinished">Importe para -fallbackfee=&lt;amount&gt;: «%s» inválido</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
+ <translation type="unfinished">Importe para -paytxfee=&lt;amount&gt;: «%s» inválido (debe ser al menos %s)</translation>
+ </message>
+ <message>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation type="unfinished">Máscara de red especificada en -whitelist: «%s» inválida</translation>
+ </message>
+ <message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">La escucha para conexiones entrantes falló (la escucha devolvió el error %s)</translation>
</message>
<message>
<source>Loading P2P addresses…</source>
@@ -557,7 +947,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Loading banlist…</source>
- <translation type="unfinished">Cargando banlist...</translation>
+ <translation type="unfinished">Cargando lista de bloqueos...</translation>
</message>
<message>
<source>Loading block index…</source>
@@ -569,29 +959,41 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Missing amount</source>
- <translation type="unfinished">Cantidad faltante</translation>
+ <translation type="unfinished">Importe faltante</translation>
</message>
<message>
<source>Missing solving data for estimating transaction size</source>
<translation type="unfinished">Faltan datos de resolución para estimar el tamaño de las transacciones</translation>
</message>
<message>
+ <source>Need to specify a port with -whitebind: '%s'</source>
+ <translation type="unfinished">Necesita especificar un puerto con -whitebind: «%s»</translation>
+ </message>
+ <message>
<source>No addresses available</source>
<translation type="unfinished">Sin direcciones disponibles</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">No se ha especificado un servidor de proxy. Use -proxy=&lt;ip&gt;o -proxy=&lt;ip:port&gt;.</translation>
+ <source>Not enough file descriptors available.</source>
+ <translation type="unfinished">No hay suficientes descriptores de archivo disponibles.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">"Prune mode" es incompatible with -txindex.</translation>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation type="unfinished">La poda no se puede configurar con un valor negativo.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation type="unfinished">El modo de poda es incompatible con -txindex.</translation>
</message>
<message>
<source>Pruning blockstore…</source>
<translation type="unfinished">Podando almacén de bloques…</translation>
</message>
<message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation type="unfinished">Reduciendo -maxconnections de %d a %d, debido a limitaciones del sistema.</translation>
+ </message>
+ <message>
<source>Replaying blocks…</source>
<translation type="unfinished">Reproduciendo bloques…</translation>
</message>
@@ -616,16 +1018,76 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">SQLiteDatabase: id aplicación inesperada. Esperado %u, tiene %u</translation>
</message>
<message>
+ <source>Section [%s] is not recognized.</source>
+ <translation type="unfinished">Sección [%s] no reconocida.</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation type="unfinished">Firma de transacción fallida</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation type="unfinished">No existe -walletdir «%s» especificada</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation type="unfinished">Ruta relativa para -walletdir «%s» especificada</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation type="unfinished">No existe directorio para -walletdir «%s» especificada</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation type="unfinished">No existe directorio de bloques «%s» especificado.</translation>
+ </message>
+ <message>
<source>Starting network threads…</source>
<translation type="unfinished">Iniciando procesos de red...</translation>
</message>
<message>
+ <source>The source code is available from %s.</source>
+ <translation type="unfinished">El código fuente esta disponible desde %s.</translation>
+ </message>
+ <message>
<source>The specified config file %s does not exist</source>
<translation type="unfinished">El archivo de configuración especificado %s no existe </translation>
</message>
<message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation type="unfinished">El importe de la transacción es muy pequeño para pagar la comisión</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation type="unfinished">El monedero evitará pagar menos de la comisión mínima de retransmisión. </translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation type="unfinished">Este es un software experimental.</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation type="unfinished">Esta es la comisión mínima que pagarás en cada transacción.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation type="unfinished">Esta es la comisión por transacción a pagar si realiza una transacción.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation type="unfinished">Importe de la transacción muy pequeño</translation>
+ </message>
+ <message>
<source>Transaction amounts must not be negative</source>
- <translation type="unfinished">Los montos de la transacción no deben ser negativos</translation>
+ <translation type="unfinished">Los importes de la transacción no deben ser negativos</translation>
+ </message>
+ <message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Ãndice de salida de cambio de transacción fuera de rango</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation type="unfinished">La transacción lleva largo tiempo en la piscina de memoria</translation>
</message>
<message>
<source>Transaction must have at least one recipient</source>
@@ -640,18 +1102,82 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Transacción demasiado grande</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">No se ha podido reservar memoria para -maxsigcachesize: «%s» MiB</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation type="unfinished">No es posible conectar con %s en este sistema (bind ha devuelto el error %s)</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation type="unfinished">No se ha podido conectar con %s en este equipo. %s es posible que esté todavía en ejecución.</translation>
+ </message>
+ <message>
+ <source>Unable to create the PID file '%s': %s</source>
+ <translation type="unfinished">No es posible crear el fichero PID «%s»: %s</translation>
+ </message>
+ <message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">No se encuentra UTXO para entrada externa</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation type="unfinished">No es posible generar las claves iniciales</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation type="unfinished">No es posible generar claves</translation>
+ </message>
+ <message>
<source>Unable to open %s for writing</source>
<translation type="unfinished">No se ha podido abrir %s para escribir</translation>
</message>
<message>
<source>Unable to parse -maxuploadtarget: '%s'</source>
- <translation type="unfinished">No se ha podido analizar -maxuploadtarget: '%s'</translation>
+ <translation type="unfinished">No se ha podido analizar -maxuploadtarget: «%s»</translation>
+ </message>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation type="unfinished">No se ha podido iniciar el servidor HTTP. Ver registro de depuración para detalles.</translation>
+ </message>
+ <message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">Fallo al descargar el monedero antes de la migración</translation>
+ </message>
+ <message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation type="unfinished">Valor -blockfilterindex %s desconocido.</translation>
+ </message>
+ <message>
+ <source>Unknown address type '%s'</source>
+ <translation type="unfinished">Tipo de dirección «%s» desconocida</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation type="unfinished">Tipo de cambio «%s» desconocido</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation type="unfinished">Red especificada en -onlynet: «%s» desconocida</translation>
</message>
<message>
<source>Unknown new rules activated (versionbit %i)</source>
<translation type="unfinished">Nuevas reglas desconocidas activadas (versionbit %i)</translation>
</message>
<message>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">Nivel de registro de depuración global -loglevel=%s no soportado. Valores válidos: %s.</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Categoría de registro no soportada %s=%s. </translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation type="unfinished">El comentario del Agente de Usuario (%s) contiene caracteres inseguros.</translation>
+ </message>
+ <message>
<source>Verifying blocks…</source>
<translation type="unfinished">Verificando bloques...</translation>
</message>
@@ -659,7 +1185,11 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<source>Verifying wallet(s)…</source>
<translation type="unfinished">Verificando monedero(s)...</translation>
</message>
- </context>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation type="unfinished">Es necesario reescribir el monedero: reiniciar %s para completar</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
@@ -732,12 +1262,32 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Enviar monedas a una dirección Bitcoin</translation>
</message>
<message>
+ <source>Backup wallet to another location</source>
+ <translation type="unfinished">Respaldar monedero en otra ubicación</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation type="unfinished">Cambiar la contraseña utilizada para el cifrado del monedero</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation type="unfinished">&amp;Enviar</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation type="unfinished">&amp;Recibir</translation>
+ </message>
+ <message>
<source>&amp;Options…</source>
<translation type="unfinished">&amp;Opciones...</translation>
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
- <translation type="unfinished">&amp;Cifrar monedero</translation>
+ <translation type="unfinished">Cifrar &amp;monedero...</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">Cifrar las claves privadas de tu monedero</translation>
</message>
<message>
<source>&amp;Backup Wallet…</source>
@@ -752,12 +1302,20 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Firmar &amp;mensaje...</translation>
</message>
<message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished">Firmar un mensaje para probar que eres dueño de esta dirección</translation>
+ </message>
+ <message>
<source>&amp;Verify message…</source>
<translation type="unfinished">&amp;Verificar mensaje...</translation>
</message>
<message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">Verificar mensajes comprobando que están firmados con direcciones Bitcoin concretas</translation>
+ </message>
+ <message>
<source>&amp;Load PSBT from file…</source>
- <translation type="unfinished">&amp;Cargar PSBT desde archivo...</translation>
+ <translation type="unfinished">&amp;Cargar TBPF desde archivo...</translation>
</message>
<message>
<source>Open &amp;URI…</source>
@@ -765,23 +1323,35 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Close Wallet…</source>
- <translation type="unfinished">Cerrar cartera...</translation>
+ <translation type="unfinished">Cerrar monedero...</translation>
</message>
<message>
<source>Create Wallet…</source>
- <translation type="unfinished">Crear cartera...</translation>
+ <translation type="unfinished">Crear monedero...</translation>
</message>
<message>
<source>Close All Wallets…</source>
- <translation type="unfinished">Cerrar todas las carteras...</translation>
+ <translation type="unfinished">Cerrar todos los monederos...</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation type="unfinished">&amp;Archivo</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation type="unfinished">&amp;Configuración</translation>
</message>
<message>
<source>&amp;Help</source>
<translation type="unfinished">&amp;Ayuda</translation>
</message>
<message>
+ <source>Tabs toolbar</source>
+ <translation type="unfinished">Barra de pestañas</translation>
+ </message>
+ <message>
<source>Syncing Headers (%1%)…</source>
- <translation type="unfinished">Sincronizando cabeceras (1%1%)</translation>
+ <translation type="unfinished">Sincronizando cabeceras (%1%)...</translation>
</message>
<message>
<source>Synchronizing with network…</source>
@@ -797,24 +1367,52 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Reindexing blocks on disk…</source>
- <translation type="unfinished">Reindexando bloques en disco</translation>
+ <translation type="unfinished">Reindexando bloques en disco...</translation>
</message>
<message>
<source>Connecting to peers…</source>
- <translation type="unfinished">Conectando con compañeros...</translation>
+ <translation type="unfinished">Conectando con pares...</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation type="unfinished">Solicitar pagos (genera código QR y URI's de Bitcoin)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation type="unfinished">Editar la lista de las direcciones y etiquetas almacenadas</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation type="unfinished">Mostrar la lista de direcciones de envío y etiquetas</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation type="unfinished">&amp;Opciones de línea de comandos</translation>
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Procesado %n bloque del historial de transacciones.</numerusform>
+ <numerusform>Procesado %n bloques del historial de transacciones.</numerusform>
</translation>
</message>
<message>
+ <source>%1 behind</source>
+ <translation type="unfinished">%1 detrás</translation>
+ </message>
+ <message>
<source>Catching up…</source>
<translation type="unfinished">Poniéndose al día...</translation>
</message>
<message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation type="unfinished">El último bloque recibido fue generado hace %1 horas.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation type="unfinished">Las transacciones posteriores aún no son visibles.</translation>
+ </message>
+ <message>
<source>Warning</source>
<translation type="unfinished">Advertencia</translation>
</message>
@@ -823,18 +1421,38 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Información</translation>
</message>
<message>
+ <source>Up to date</source>
+ <translation type="unfinished">Actualizado al día </translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction</source>
<translation type="unfinished">Cargar una transacción de Bitcoin parcialmente firmada</translation>
</message>
<message>
<source>Load PSBT from &amp;clipboard…</source>
- <translation type="unfinished">Cargar PSBT desde &amp;portapapeles</translation>
+ <translation type="unfinished">Cargar TBPF desde &amp;portapapeles...</translation>
</message>
<message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Cargar una transacción de Bitcoin parcialmente firmada desde el Portapapeles</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation type="unfinished">Ventana del nodo</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished">Direcciones de &amp;envío</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished">Direcciones de &amp;recepción</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation type="unfinished">Abrir un bitcoin: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation type="unfinished">Abrir Monedero</translation>
</message>
@@ -847,16 +1465,30 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Cerrar monedero</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Restaurar monedero…</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Restaurar monedero desde un archivo de respaldo</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Cerrar todos los monederos</translation>
</message>
<message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation type="unfinished">Muestra el mensaje de ayuda %1 para obtener una lista con posibles opciones de línea de comandos de Bitcoin.</translation>
+ </message>
+ <message>
<source>&amp;Mask values</source>
<translation type="unfinished">&amp;Ocultar valores</translation>
</message>
<message>
<source>Mask the values in the Overview tab</source>
- <translation type="unfinished">Esconder los valores de la ventana de previsualización</translation>
+ <translation type="unfinished">Ocultar los valores de la ventana de previsualización</translation>
</message>
<message>
<source>default wallet</source>
@@ -867,26 +1499,66 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">No hay monederos disponibles</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Datos del monedero </translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Cargar copia de seguridad del monedero</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Restaurar monedero</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nombre del monedero</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Ventana</translation>
</message>
+ <message>
+ <source>Zoom</source>
+ <translation type="unfinished">Acercar</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation type="unfinished">Ventana principal</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation type="unfinished">%1 cliente</translation>
+ </message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Ocultar </translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">&amp;Mostrar</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n conexión activa con la red Bitcoin.</numerusform>
+ <numerusform>%n conexiones activas con la red Bitcoin.</numerusform>
</translation>
</message>
<message>
<source>Click for more actions.</source>
<extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
- <translation type="unfinished">Haz click para ver más acciones.</translation>
+ <translation type="unfinished">Haz clic para ver más acciones.</translation>
</message>
<message>
<source>Show Peers tab</source>
<extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
- <translation type="unfinished">Mostrar pestaña Pares</translation>
+ <translation type="unfinished">Mostrar pestaña de pares</translation>
</message>
<message>
<source>Disable network activity</source>
@@ -899,6 +1571,10 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Habilitar la actividad de la red</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Presincronizando cabeceras (%1%)...</translation>
+ </message>
+ <message>
<source>Warning: %1</source>
<translation type="unfinished">Advertencia: %1</translation>
</message>
@@ -911,7 +1587,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<message>
<source>Amount: %1
</source>
- <translation type="unfinished">Cantidad: %1
+ <translation type="unfinished">Importe: %1
</translation>
</message>
<message>
@@ -921,6 +1597,12 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</translation>
</message>
<message>
+ <source>Type: %1
+</source>
+ <translation type="unfinished">Tipo: %1
+</translation>
+ </message>
+ <message>
<source>Label: %1
</source>
<translation type="unfinished">Etiqueta: %1
@@ -938,11 +1620,27 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Incoming transaction</source>
- <translation type="unfinished">Transacción entrante</translation>
+ <translation type="unfinished">Transacción recibida</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation type="unfinished">La generación de clave HD está &lt;b&gt;habilitada&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">La generación de clave HD está &lt;b&gt;deshabilitada&lt;/b&gt;</translation>
</message>
<message>
<source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation type="unfinished">Llave privada &lt;b&gt;deshabilitada&lt;/b&gt;</translation>
+ <translation type="unfinished">Clave privada &lt;b&gt;deshabilitada&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation type="unfinished">El monedero está &lt;b&gt;cifrado&lt;/b&gt; y actualmente &lt;b&gt;desbloqueado&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation type="unfinished">El monedero está &lt;b&gt;cifrado&lt;/b&gt; y actualmente &lt;b&gt;bloqueado&lt;/b&gt;</translation>
</message>
<message>
<source>Original message:</source>
@@ -950,6 +1648,13 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
</context>
<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">Unidad en la que se muestran los importes. Haga clic para seleccionar otra unidad.</translation>
+ </message>
+</context>
+<context>
<name>CoinControlDialog</name>
<message>
<source>Coin Selection</source>
@@ -961,13 +1666,17 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Amount:</source>
- <translation type="unfinished">Cuantía:</translation>
+ <translation type="unfinished">Importe:</translation>
</message>
<message>
<source>Fee:</source>
<translation type="unfinished">Comisión:</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation type="unfinished">Polvo:</translation>
+ </message>
+ <message>
<source>After Fee:</source>
<translation type="unfinished">Después de la comisión:</translation>
</message>
@@ -981,15 +1690,23 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Tree mode</source>
- <translation type="unfinished">Modo Ãrbol</translation>
+ <translation type="unfinished">Modo árbol</translation>
</message>
<message>
<source>List mode</source>
- <translation type="unfinished">Modo Lista</translation>
+ <translation type="unfinished">Modo lista</translation>
</message>
<message>
<source>Amount</source>
- <translation type="unfinished">Cantidad</translation>
+ <translation type="unfinished">Importe</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation type="unfinished">Recibido con dirección</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation type="unfinished">Recibido con etiqueta</translation>
</message>
<message>
<source>Date</source>
@@ -1004,16 +1721,20 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Confirmado</translation>
</message>
<message>
+ <source>Copy amount</source>
+ <translation type="unfinished">Copiar importe</translation>
+ </message>
+ <message>
<source>&amp;Copy address</source>
- <translation type="unfinished">copiar dirección </translation>
+ <translation type="unfinished">&amp;Copiar dirección</translation>
</message>
<message>
<source>Copy &amp;label</source>
- <translation type="unfinished">Copiar &amp;label</translation>
+ <translation type="unfinished">Copiar &amp;etiqueta</translation>
</message>
<message>
<source>Copy &amp;amount</source>
- <translation type="unfinished">Copiar &amp;amount</translation>
+ <translation type="unfinished">Copiar &amp;importe</translation>
</message>
<message>
<source>Copy transaction &amp;ID and output index</source>
@@ -1021,13 +1742,17 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>L&amp;ock unspent</source>
- <translation type="unfinished">Bloquear no gastado</translation>
+ <translation type="unfinished">B&amp;loquear no gastado</translation>
</message>
<message>
<source>&amp;Unlock unspent</source>
<translation type="unfinished">&amp;Desbloquear lo no gastado</translation>
</message>
<message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">Copiar cantidad</translation>
+ </message>
+ <message>
<source>Copy fee</source>
<translation type="unfinished">Copiar comisión</translation>
</message>
@@ -1036,14 +1761,34 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Copiar después de la comisión</translation>
</message>
<message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">Copiar bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">Copiar polvo</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation type="unfinished">Copiar cambio</translation>
</message>
<message>
+ <source>(%1 locked)</source>
+ <translation type="unfinished">(%1 bloqueado)</translation>
+ </message>
+ <message>
<source>yes</source>
<translation type="unfinished">sí</translation>
</message>
<message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation type="unfinished">Esta etiqueta se vuelve roja si algún receptor recibe un importe inferior al umbral actual establecido para el polvo.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation type="unfinished">Puede variar en +/- %1 satoshi(s) por entrada.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(sin etiqueta)</translation>
</message>
@@ -1061,25 +1806,29 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<message>
<source>Create Wallet</source>
<extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
- <translation type="unfinished">Crear Monedero</translation>
+ <translation type="unfinished">Crear monedero</translation>
</message>
<message>
<source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
<extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
- <translation type="unfinished">Creando Monedero &lt;b&gt;%1&lt;/b&gt;…</translation>
+ <translation type="unfinished">Creando monedero &lt;b&gt;%1&lt;/b&gt;…</translation>
</message>
<message>
<source>Create wallet failed</source>
- <translation type="unfinished">Crear monedero ha fallado</translation>
+ <translation type="unfinished">Fallo al crear monedero</translation>
</message>
<message>
<source>Create wallet warning</source>
- <translation type="unfinished">Advertencia sobre crear monedero</translation>
+ <translation type="unfinished">Advertencia al crear monedero</translation>
</message>
<message>
<source>Can't list signers</source>
<translation type="unfinished">No se pueden enumerar los firmantes</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Se han encontrado demasiados firmantes externos</translation>
+ </message>
</context>
<context>
<name>LoadWalletsActivity</name>
@@ -1098,25 +1847,53 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<name>OpenWalletActivity</name>
<message>
<source>Open wallet failed</source>
- <translation type="unfinished">Abrir monedero ha fallado</translation>
+ <translation type="unfinished">Fallo al abrir monedero</translation>
</message>
<message>
<source>Open wallet warning</source>
- <translation type="unfinished">Advertencia sobre crear monedero</translation>
+ <translation type="unfinished">Advertencia al abrir monedero</translation>
</message>
<message>
<source>default wallet</source>
- <translation type="unfinished">Monedero predeterminado</translation>
+ <translation type="unfinished">monedero predeterminado</translation>
</message>
<message>
<source>Open Wallet</source>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
- <translation type="unfinished">Abrir Monedero</translation>
+ <translation type="unfinished">Abrir monedero</translation>
</message>
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
<extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
- <translation type="unfinished">Abriendo Monedero &lt;b&gt;%1&lt;/b&gt;...</translation>
+ <translation type="unfinished">Abriendo monedero &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
+<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Restaurar monedero</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Restaurando monedero &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Fallo al restaurar monedero</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Advertencia al restaurar monedero</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Mensaje al restaurar monedero</translation>
</message>
</context>
<context>
@@ -1130,6 +1907,10 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">¿Estás seguro de que deseas cerrar el monedero &lt;i&gt;%1&lt;/i&gt;?</translation>
</message>
<message>
+ <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
+ <translation type="unfinished">Cerrar el monedero durante demasiado tiempo puede causar la resincronización de toda la cadena si la poda es habilitada.</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Cerrar todos los monederos</translation>
</message>
@@ -1142,11 +1923,11 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<name>CreateWalletDialog</name>
<message>
<source>Create Wallet</source>
- <translation type="unfinished">Crear Monedero</translation>
+ <translation type="unfinished">Crear monedero</translation>
</message>
<message>
<source>Wallet Name</source>
- <translation type="unfinished">Nombre del Monedero</translation>
+ <translation type="unfinished">Nombre del monedero</translation>
</message>
<message>
<source>Wallet</source>
@@ -1158,15 +1939,27 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Encrypt Wallet</source>
- <translation type="unfinished">Cifrar Monedero</translation>
+ <translation type="unfinished">Cifrar monedero</translation>
</message>
<message>
<source>Advanced Options</source>
- <translation type="unfinished">Opciones Avanzadas</translation>
+ <translation type="unfinished">Opciones avanzadas</translation>
+ </message>
+ <message>
+ <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">Deshabilita las claves privadas para este monedero. Los monederos con claves privadas deshabilitadas no tendrán claves privadas y no podrán tener ni una semilla HD ni claves privadas importadas. Esto es ideal para monederos de solo observación.</translation>
</message>
<message>
<source>Disable Private Keys</source>
- <translation type="unfinished">Deshabilita las Llaves Privadas</translation>
+ <translation type="unfinished">Deshabilita las claves privadas</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Crear un monedero vacío. Los monederos vacíos no tienen claves privadas ni scripts. Las claves privadas y direcciones pueden importarse después o también establecer una semilla HD.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation type="unfinished">Crear monedero vacío</translation>
</message>
<message>
<source>Use descriptors for scriptPubKey management</source>
@@ -1202,23 +1995,55 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
- <translation type="unfinished">Editar Dirección</translation>
+ <translation type="unfinished">Editar dirección</translation>
</message>
<message>
<source>&amp;Label</source>
<translation type="unfinished">&amp;Etiqueta</translation>
</message>
<message>
+ <source>The label associated with this address list entry</source>
+ <translation type="unfinished">La etiqueta asociada con esta entrada en la lista de direcciones</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation type="unfinished">La dirección asociada con esta entrada en la guía. Solo puede ser modificada para direcciones de envío.</translation>
+ </message>
+ <message>
<source>&amp;Address</source>
<translation type="unfinished">&amp;Dirección</translation>
</message>
<message>
+ <source>New sending address</source>
+ <translation type="unfinished">Nueva dirección de envío</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation type="unfinished">Editar dirección de recepción</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation type="unfinished">Editar dirección de envio</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation type="unfinished">La dirección introducida «%1» no es una dirección Bitcoin válida.</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation type="unfinished">La dirección «%1» ya existe como dirección de recepción con la etiqueta «%2» y, por lo tanto, no se puede agregar como dirección de envío.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation type="unfinished">La dirección introducida «%1» ya se encuentra en la libreta de direcciones con la etiqueta «%2».</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">No se pudo desbloquear el monedero.</translation>
</message>
<message>
<source>New key generation failed.</source>
- <translation type="unfinished">La generación de la nueva clave fallo</translation>
+ <translation type="unfinished">Fallo en la generación de la nueva clave.</translation>
</message>
</context>
<context>
@@ -1231,26 +2056,71 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<source>name</source>
<translation type="unfinished">nombre</translation>
</message>
- </context>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation type="unfinished">El directorio ya existe. Agrega %1 si tiene la intención de crear un nuevo directorio aquí.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation type="unfinished">La ruta ya existe, y no es un directorio.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation type="unfinished">No puede crear directorio de datos aquí.</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n GB de espacio disponible</numerusform>
+ <numerusform>%n GB de espacio disponible</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(de %n GB necesario)</numerusform>
+ <numerusform>(de %n GB necesarios)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n GB necesario para completar la cadena de bloques)</numerusform>
+ <numerusform>(%n GB necesarios para completar la cadena de bloques)</numerusform>
+ </translation>
+ </message>
<message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(de %1 GB necesarios)</translation>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation type="unfinished">Al menos %1 GB de información será almacenada en este directorio, y seguirá creciendo a través del tiempo.</translation>
</message>
<message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB necesarios para la cadena completa)</translation>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation type="unfinished">Aproximadamente %1 GB de información será almacenada en este directorio.</translation>
</message>
<message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>(suficiente para restaurar copias de seguridad de %n día de antigüedad)</numerusform>
+ <numerusform>(suficiente para restaurar copias de seguridad de %n días de antigüedad)</numerusform>
</translation>
</message>
<message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation type="unfinished">%1 descargará y almacenará una copia de la cadena de bloques de Bitcoin.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation type="unfinished">El monedero también se almacenará en este directorio.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation type="unfinished">Error: El directorio de datos especificado «%1» no pudo ser creado.</translation>
+ </message>
+ <message>
<source>Welcome</source>
<translation type="unfinished">Bienvenido</translation>
</message>
@@ -1259,14 +2129,42 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Bienvenido a %1.</translation>
</message>
<message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation type="unfinished">Al ser esta la primera vez que se ejecuta el programa, puedes escoger donde %1 almacenará los datos.</translation>
+ </message>
+ <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Limitar el almacenamiento de cadena de bloques a</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Al revertir este ajuste se requiere volver a descargar la cadena de bloques completa. Es más rápido descargar primero la cadena completa y después podarla. Desactiva algunas características avanzadas.</translation>
+ </message>
+ <message>
<source> GB</source>
<translation type="unfinished">GB</translation>
</message>
- </context>
+ <message>
+ <source>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>
+ <translation type="unfinished">El primer proceso de sincronización consume muchos recursos, y es posible que puedan ocurrir problemas de hardware que anteriormente no hayas notado. Cada vez que ejecutes %1 automáticamente se reiniciará el proceso de sincronización desde el punto que lo dejaste anteriormente.</translation>
+ </message>
+ <message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">Cuando hagas clic en OK, %1 se iniciará la descarga y procesamiento de toda la cadena %4 de bloques (%2 GB) empezando con las primeras transacciones en %3 cuando %4 fue inicialmente lanzado.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation type="unfinished">Si ha elegido limitar el almacenamiento de la cadena de bloques (pruning o poda), los datos históricos todavía se deben descargar y procesar, pero se eliminarán posteriormente para mantener el uso del disco bajo.</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation type="unfinished">Usa el directorio de datos predeterminado</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation type="unfinished">Usa un directorio de datos personalizado:</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
<message>
@@ -1275,9 +2173,13 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>About %1</source>
- <translation type="unfinished">Alrededor de %1</translation>
+ <translation type="unfinished">Acerca de %1</translation>
</message>
- </context>
+ <message>
+ <source>Command-line options</source>
+ <translation type="unfinished">&amp;Opciones de línea de comandos</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
<message>
@@ -1292,6 +2194,22 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<context>
<name>ModalOverlay</name>
<message>
+ <source>Form</source>
+ <translation type="unfinished">Formulario</translation>
+ </message>
+ <message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation type="unfinished">Es posible que las transacciones recientes aún no estén visibles y por lo tanto, el saldo de su monedero podría ser incorrecto. Esta información será correcta una vez que su monedero haya terminado de sincronizarse con la red bitcoin, como se detalla a continuación.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation type="unfinished">La red no aceptará intentar gastar bitcoins que se vean afectados por transacciones aún no mostradas.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation type="unfinished">Numero de bloques pendientes</translation>
+ </message>
+ <message>
<source>Unknown…</source>
<translation type="unfinished">Desconocido...</translation>
</message>
@@ -1300,6 +2218,10 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">calculando...</translation>
</message>
<message>
+ <source>Last block time</source>
+ <translation type="unfinished">Hora del último bloque</translation>
+ </message>
+ <message>
<source>Progress</source>
<translation type="unfinished">Progreso</translation>
</message>
@@ -1308,12 +2230,36 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Incremento del progreso por hora</translation>
</message>
<message>
+ <source>Estimated time left until synced</source>
+ <translation type="unfinished">Tiempo estimado antes de sincronizar</translation>
+ </message>
+ <message>
<source>Hide</source>
- <translation type="unfinished">Ocultar </translation>
+ <translation type="unfinished">Ocultar</translation>
+ </message>
+ <message>
+ <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
+ <translation type="unfinished">%1 está actualmente sincronizándose. Descargará cabeceras y bloques de nodos semejantes y los validará hasta alcanzar la cabeza de la cadena de bloques.</translation>
</message>
<message>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
- <translation type="unfinished">Desconocido. Sincronizando Cabeceras (%1, %2%)…</translation>
+ <translation type="unfinished">Desconocido. Sincronizando cabeceras (%1, %2%)…</translation>
+ </message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Desconocido. Presincronizando cabeceras (%1, %2%)…</translation>
+ </message>
+</context>
+<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <source>Open bitcoin URI</source>
+ <translation type="unfinished">Abrir URI de bitcoin</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <extracomment>Tooltip text for button that allows you to paste an address that is in your clipboard.</extracomment>
+ <translation type="unfinished">Pegar dirección desde portapapeles</translation>
</message>
</context>
<context>
@@ -1327,17 +2273,73 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">&amp;Principal</translation>
</message>
<message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation type="unfinished">Iniciar automáticamente %1 después de iniciar sesión en el sistema.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation type="unfinished">&amp;Iniciar %1 al iniciar sesión en el sistema</translation>
+ </message>
+ <message>
<source>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>
- <translation type="unfinished">Activar el pruning reduce significativamente el espacio de disco necesario para guardar las transacciones. Todos los bloques son completamente validados de cualquier manera. Revertir esta opción requiere que descarques de nuevo toda la cadena de bloques.</translation>
+ <translation type="unfinished">Activar la poda reduce significativamente el espacio de disco necesario para guardar las transacciones. Todos los bloques son completamente validados de cualquier manera. Revertir esta opción requiere descargar de nuevo toda la cadena de bloques.</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation type="unfinished">Tamaño de la caché de la base de &amp;datos</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation type="unfinished">Número de hilos de &amp;verificación de scripts</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation type="unfinished">Dirección IP del proxy (Ejemplo. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ </message>
+ <message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation type="unfinished">Muestra si el proxy SOCKS5 por defecto se utiliza para conectarse a pares a través de este tipo de red.</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Minimizar en vez de salir de la aplicación cuando la ventana está cerrada. Cuando se activa esta opción, la aplicación sólo se cerrará después de seleccionar Salir en el menú.</translation>
+ </message>
+ <message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Las opciones establecidas en este diálogo serán invalidadas por la línea de comandos:</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation type="unfinished">Abrir el archivo de configuración %1 en el directorio de trabajo.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation type="unfinished">Abrir archivo de configuración</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation type="unfinished">Restablecer todas las opciones del cliente a los valores predeterminados.</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation type="unfinished">&amp;Restablecer opciones</translation>
</message>
<message>
<source>&amp;Network</source>
<translation type="unfinished">&amp;Red</translation>
</message>
<message>
+ <source>Prune &amp;block storage to</source>
+ <translation type="unfinished">Podar el almacenamiento de &amp;bloques a</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation type="unfinished">Revertir estas configuraciones requiere descargar de nuevo la cadena de bloques completa.</translation>
+ </message>
+ <message>
<source>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>
<extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
- <translation type="unfinished">Tamaño máximo de la caché de la base de datos. Una caché más grande puede contribuir a una sincronización más rápida, después de lo cual el beneficio es menos pronunciado para la mayoría de los casos de uso. Disminuir el tamaño de la caché reducirá el uso de la memoria. La memoria mempool no utilizada se comparte para esta caché.</translation>
+ <translation type="unfinished">Tamaño máximo de la caché de la base de datos. Una caché más grande puede contribuir a una sincronización más rápida, después de lo cual el beneficio es menos pronunciado para la mayoría de los casos de uso. Disminuir el tamaño de la caché reducirá el uso de la memoria. La memoria de la piscina de memoria no utilizada se comparte para esta caché.</translation>
</message>
<message>
<source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
@@ -1345,6 +2347,10 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Establezca el número de hilos de verificación de scripts. Los valores negativos corresponden al número de núcleos que se desea dejar libres al sistema.</translation>
</message>
<message>
+ <source>(0 = auto, &lt;0 = leave that many cores free)</source>
+ <translation type="unfinished">(0 = auto, &lt;0 = deja esa cantidad de núcleos libres)</translation>
+ </message>
+ <message>
<source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
<extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
<translation type="unfinished">Esto te permite a ti o a una herramienta de terceros comunicarse con el nodo a través de la línea de comandos y comandos JSON-RPC.</translation>
@@ -1355,9 +2361,13 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Activar servidor R&amp;PC</translation>
</message>
<message>
+ <source>W&amp;allet</source>
+ <translation type="unfinished">M&amp;onedero</translation>
+ </message>
+ <message>
<source>Whether to set subtract fee from amount as default or not.</source>
<extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
- <translation type="unfinished">Establecer si se resta la tasa del importe por defecto o no.</translation>
+ <translation type="unfinished">Establecer si se resta la comisión del importe por defecto o no.</translation>
</message>
<message>
<source>Subtract &amp;fee from amount by default</source>
@@ -1370,37 +2380,45 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation type="unfinished">Habilitar características de &amp;Control de Moneda.</translation>
+ <translation type="unfinished">Habilitar características de &amp;control de moneda.</translation>
</message>
<message>
<source>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>
<translation type="unfinished">Si deshabilitas el gasto de un cambio no confirmado, el cambio de una transacción no se puede usar hasta que esa transacción tenga al menos una confirmación. Esto también afecta a cómo se calcula tu saldo.</translation>
</message>
<message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation type="unfinished">&amp;Gastar cambio sin confirmar</translation>
+ </message>
+ <message>
<source>Enable &amp;PSBT controls</source>
<extracomment>An options window setting to enable PSBT controls.</extracomment>
- <translation type="unfinished">Activar controles &amp;PSBT</translation>
+ <translation type="unfinished">Activar controles &amp;TBPF</translation>
</message>
<message>
<source>Whether to show PSBT controls.</source>
<extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
- <translation type="unfinished">Establecer si se muestran los controles PSBT</translation>
+ <translation type="unfinished">Establecer si se muestran los controles TBPF</translation>
</message>
<message>
<source>External Signer (e.g. hardware wallet)</source>
- <translation type="unfinished">Dispositivo Externo de Firma (ej. billetera de hardware)</translation>
+ <translation type="unfinished">Dispositivo externo de firma (ej. billetera de hardware)</translation>
</message>
<message>
<source>&amp;External signer script path</source>
- <translation type="unfinished">&amp;Ruta de script de firma externo</translation>
+ <translation type="unfinished">Ruta de script de firma &amp;externo</translation>
</message>
<message>
<source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
<translation type="unfinished">Ruta completa al script compatible con Bitcoin Core (ej. C:\Descargas\hwi.exe o /Usuarios/SuUsuario/Descargas/hwi.py). Cuidado: código malicioso podría robarle sus monedas!</translation>
</message>
<message>
+ <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
+ <translation type="unfinished">Abrir automáticamente el puerto del cliente Bitcoin en el router. Esta opción solo funciona cuando el router admite UPnP y está activado.</translation>
+ </message>
+ <message>
<source>Map port using &amp;UPnP</source>
- <translation type="unfinished">Mapear el puerto usando &amp;UPnp</translation>
+ <translation type="unfinished">Mapear el puerto usando &amp;UPnP</translation>
</message>
<message>
<source>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>
@@ -1416,7 +2434,31 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Allow incomin&amp;g connections</source>
- <translation type="unfinished">Permitir conexiones entrantes</translation>
+ <translation type="unfinished">&amp;Permitir conexiones entrantes</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation type="unfinished">Conectar a la red de Bitcoin a través de un proxy SOCKS5.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation type="unfinished">&amp;Conectar a través del proxy SOCKS5 (proxy predeterminado):</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation type="unfinished">&amp;IP proxy::</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation type="unfinished">&amp;Puerto:</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation type="unfinished">Puerto del proxy (ej. 9050)</translation>
+ </message>
+ <message>
+ <source>Used for reaching peers via:</source>
+ <translation type="unfinished">Utilizado para llegar a los pares a través de:</translation>
</message>
<message>
<source>&amp;Window</source>
@@ -1424,27 +2466,55 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Show the icon in the system tray.</source>
- <translation type="unfinished">Mostrar el ícono en la bandeja del sistema.</translation>
+ <translation type="unfinished">Mostrar el icono en la bandeja del sistema.</translation>
</message>
<message>
<source>&amp;Show tray icon</source>
- <translation type="unfinished">Mostrar la bandeja del sistema.</translation>
+ <translation type="unfinished">Mostrar la &amp;bandeja del sistema.</translation>
</message>
<message>
<source>Show only a tray icon after minimizing the window.</source>
<translation type="unfinished">Mostrar solo un icono de bandeja después de minimizar la ventana.</translation>
</message>
<message>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation type="unfinished">&amp;Minimiza a la bandeja en vez de la barra de tareas</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation type="unfinished">M&amp;inimizar al cerrar</translation>
+ </message>
+ <message>
<source>&amp;Display</source>
<translation type="unfinished">&amp;Mostrar</translation>
</message>
<message>
+ <source>User Interface &amp;language:</source>
+ <translation type="unfinished">&amp;Idioma de la interfaz de usuario:</translation>
+ </message>
+ <message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation type="unfinished">El idioma de la interfaz de usuario puede establecerse aquí. Esta configuración tendrá efecto después de reiniciar %1.</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation type="unfinished">&amp;Unidad en la que mostrar importes:</translation>
+ </message>
+ <message>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation type="unfinished">Elegir la subdivisión predeterminada para mostrar cantidades en la interfaz y cuando se envían monedas.</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">URLs de terceros (por ejemplo, un explorador de bloques) que aparecen en la pestaña de transacciones como elementos del menú contextual. %s en la URL se sustituye por el hash de la transacción. Las URL múltiples se separan con una barra vertical |.</translation>
</message>
<message>
<source>&amp;Third-party transaction URLs</source>
- <translation type="unfinished">URLs de transacciones de &amp;Terceros</translation>
+ <translation type="unfinished">URLs de transacciones de &amp;terceros</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation type="unfinished">Mostrar o no funcionalidad del control de moneda</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
@@ -1452,19 +2522,23 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
- <translation type="unfinished">Usar proxy SOCKS&amp;5 para alcanzar nodos via servicios ocultos Tor:</translation>
+ <translation type="unfinished">Usar proxy SOCKS&amp;5 para alcanzar nodos vía servicios anónimos Tor:</translation>
</message>
<message>
<source>Monospaced font in the Overview tab:</source>
- <translation type="unfinished">letra Monospace en la pestaña Resumen: </translation>
+ <translation type="unfinished">Fuente monoespaciada en la pestaña Resumen:</translation>
</message>
<message>
<source>embedded "%1"</source>
- <translation type="unfinished">incrustado "%1"</translation>
+ <translation type="unfinished">incrustado «%1»</translation>
</message>
<message>
<source>closest matching "%1"</source>
- <translation type="unfinished">coincidencia más aproximada "%1"</translation>
+ <translation type="unfinished">coincidencia más aproximada «%1»</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation type="unfinished">&amp;Cancelar</translation>
</message>
<message>
<source>Compiled without external signing support (required for external signing)</source>
@@ -1481,14 +2555,22 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirmar restablecimiento de opciones</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Es necesario reiniciar el cliente para activar los cambios.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Los ajustes actuales se guardarán en «%1».</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">El cliente se cerrará. ¿Deseas continuar?</translation>
</message>
<message>
@@ -1497,6 +2579,11 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Opciones de configuración</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Explanatory text about the priority order of instructions considered by client. The order from high to low being: command-line, configuration file, GUI settings.</extracomment>
+ <translation type="unfinished">El archivo de configuración se utiliza para especificar opciones de usuario avanzadas que anulan la configuración de la GUI. Además, cualquier opción de línea de comandos anulará este archivo de configuración.</translation>
+ </message>
+ <message>
<source>Continue</source>
<translation type="unfinished">Continuar</translation>
</message>
@@ -1518,14 +2605,25 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">No se puede leer el ajuste «%1», %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
<translation type="unfinished">Formulario</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">La información mostrada puede estar desactualizada. Su monedero se sincroniza automáticamente con la red de Bitcoin después de establecer una conexión, pero este proceso aún no se ha completado.</translation>
+ </message>
+ <message>
<source>Watch-only:</source>
- <translation type="unfinished">Solo lectura:</translation>
+ <translation type="unfinished">Solo observación:</translation>
</message>
<message>
<source>Available:</source>
@@ -1544,24 +2642,44 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
<translation type="unfinished">Total de transacciones que aún no se han sido confirmadas, y que no son contabilizadas dentro del saldo disponible para gastar</translation>
</message>
<message>
+ <source>Immature:</source>
+ <translation type="unfinished">No disponible:</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation type="unfinished">Saldo recién minado que aún no está disponible</translation>
+ </message>
+ <message>
<source>Your current total balance</source>
<translation type="unfinished">Saldo total actual</translation>
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation type="unfinished">Su saldo actual en direcciones solo-lectura</translation>
+ <translation type="unfinished">Su saldo actual en direcciones de observación</translation>
</message>
<message>
<source>Spendable:</source>
- <translation type="unfinished">Gastable:</translation>
+ <translation type="unfinished">Disponible:</translation>
</message>
<message>
<source>Recent transactions</source>
<translation type="unfinished">Transaciones recientes</translation>
</message>
<message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation type="unfinished">Transacciones sin confirmar a direcciones de observación</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation type="unfinished">Saldo minado en direcciones de observación que aún no está disponible</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation type="unfinished">Saldo total actual en direcciones de observación</translation>
+ </message>
+ <message>
<source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
- <translation type="unfinished">Modo de privacidad activado para la pestaña de visión general. Para desenmascarar los valores, desmarcar los valores de Configuración-&gt;Máscara.</translation>
+ <translation type="unfinished">Modo de privacidad activado para la pestaña de visión general. Para desenmascarar los valores, desmarcar los valores de Configuración-&gt;Enmascarar valores.</translation>
</message>
</context>
<context>
@@ -1600,7 +2718,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Cannot sign inputs while wallet is locked.</source>
- <translation type="unfinished">No se pueden firmar las entradas mientras la billetera está bloqueada.</translation>
+ <translation type="unfinished">No se pueden firmar las entradas mientras el monedero está bloqueado.</translation>
</message>
<message>
<source>Could not sign any more inputs.</source>
@@ -1628,7 +2746,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>PSBT copied to clipboard.</source>
- <translation type="unfinished">PSBT copiado al portapapeles</translation>
+ <translation type="unfinished">TBPF copiado al portapapeles</translation>
</message>
<message>
<source>Save Transaction Data</source>
@@ -1641,7 +2759,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>PSBT saved to disk.</source>
- <translation type="unfinished">PSBT guardado en la memoria.</translation>
+ <translation type="unfinished">TBPF guardado en disco.</translation>
</message>
<message>
<source> * Sends %1 to %2</source>
@@ -1649,7 +2767,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Unable to calculate transaction fee or total transaction amount.</source>
- <translation type="unfinished">No se ha podido calcular la comisión por transacción o la totalidad de la cantidad de la transacción.</translation>
+ <translation type="unfinished">No se ha podido calcular la comisión por transacción o la totalidad del importe de la transacción.</translation>
</message>
<message>
<source>Pays transaction fee: </source>
@@ -1657,7 +2775,7 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Total Amount</source>
- <translation type="unfinished">Cantidad Total</translation>
+ <translation type="unfinished">Importe total</translation>
</message>
<message>
<source>or</source>
@@ -1693,12 +2811,28 @@ Firmar solo es posible con direcciones del tipo Legacy.</translation>
</message>
<message>
<source>Transaction status is unknown.</source>
- <translation type="unfinished">El estatus de la transacción es desconocido.</translation>
+ <translation type="unfinished">El estado de la transacción es desconocido.</translation>
</message>
</context>
<context>
<name>PaymentServer</name>
<message>
+ <source>Payment request error</source>
+ <translation type="unfinished">Error en la solicitud de pago</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation type="unfinished">No se puede iniciar bitcoin: controlador clic-para-pagar</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation type="unfinished">Gestión de URI</translation>
+ </message>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation type="unfinished">«bitcoin: //» no es un URI válido. Use «bitcoin:» en su lugar.</translation>
+ </message>
+ <message>
<source>Cannot process payment request because BIP70 is not supported.
Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
@@ -1706,15 +2840,38 @@ If you are receiving this error you should request the merchant provide a BIP21
Debido a los fallos de seguridad generalizados en el BIP70, se recomienda encarecidamente ignorar las instrucciones del comerciante para cambiar de monedero.
Si recibe este error, debe solicitar al comerciante que le proporcione un URI compatible con BIP21.</translation>
</message>
- </context>
+ <message>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation type="unfinished">¡No se puede interpretar la URI! Esto puede deberse a una dirección Bitcoin inválida o a parámetros de URI mal formados.</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation type="unfinished">Gestión del archivo de solicitud de pago</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>User Agent</source>
+ <extracomment>Title of Peers Table column which contains the peer's User Agent string.</extracomment>
+ <translation type="unfinished">Agente del usuario</translation>
+ </message>
+ <message>
<source>Peer</source>
<extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
<translation type="unfinished">Pares</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Duración</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
+ <translation type="unfinished">Sentido</translation>
+ </message>
+ <message>
<source>Sent</source>
<extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
<translation type="unfinished">Enviado</translation>
@@ -1730,11 +2887,26 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
<translation type="unfinished">Dirección</translation>
</message>
<message>
+ <source>Type</source>
+ <extracomment>Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</extracomment>
+ <translation type="unfinished">Tipo</translation>
+ </message>
+ <message>
<source>Network</source>
<extracomment>Title of Peers Table column which states the network the peer connected through.</extracomment>
<translation type="unfinished">Red</translation>
</message>
- </context>
+ <message>
+ <source>Inbound</source>
+ <extracomment>An Inbound Connection from a Peer.</extracomment>
+ <translation type="unfinished">Entrante</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <extracomment>An Outbound Connection to a Peer.</extracomment>
+ <translation type="unfinished">Saliente</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
<message>
@@ -1746,6 +2918,10 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
<translation type="unfinished">&amp;Copiar Imagen</translation>
</message>
<message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation type="unfinished">URI resultante demasiado larga. Intente reducir el texto de la etiqueta / mensaje.</translation>
+ </message>
+ <message>
<source>Error encoding URI into QR Code.</source>
<translation type="unfinished">Fallo al codificar URI en código QR.</translation>
</message>
@@ -1755,7 +2931,7 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>Save QR Code</source>
- <translation type="unfinished">Guardar Código QR</translation>
+ <translation type="unfinished">Guardar código QR</translation>
</message>
<message>
<source>PNG Image</source>
@@ -1771,13 +2947,25 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>Client version</source>
- <translation type="unfinished">Versión del Cliente</translation>
+ <translation type="unfinished">Versión del cliente</translation>
</message>
<message>
<source>&amp;Information</source>
<translation type="unfinished">&amp;Información</translation>
</message>
<message>
+ <source>To specify a non-default location of the data directory use the '%1' option.</source>
+ <translation type="unfinished">Para especificar una localización personalizada del directorio de datos, usa la opción «%1».</translation>
+ </message>
+ <message>
+ <source>To specify a non-default location of the blocks directory use the '%1' option.</source>
+ <translation type="unfinished">Para especificar una localización personalizada del directorio de bloques, usa la opción «%1». </translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation type="unfinished">Hora de inicio</translation>
+ </message>
+ <message>
<source>Network</source>
<translation type="unfinished">Red</translation>
</message>
@@ -1794,6 +2982,10 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
<translation type="unfinished">Cadena de bloques</translation>
</message>
<message>
+ <source>Memory Pool</source>
+ <translation type="unfinished">Piscina de memoria</translation>
+ </message>
+ <message>
<source>Current number of transactions</source>
<translation type="unfinished">Número actual de transacciones</translation>
</message>
@@ -1803,7 +2995,7 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>Wallet: </source>
- <translation type="unfinished">Monedero</translation>
+ <translation type="unfinished">Monedero:</translation>
</message>
<message>
<source>(none)</source>
@@ -1823,48 +3015,91 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>&amp;Peers</source>
- <translation type="unfinished">Pares</translation>
+ <translation type="unfinished">&amp;Pares</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation type="unfinished">Pares bloqueados</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation type="unfinished">Selecciona un par para ver la información detallada.</translation>
</message>
<message>
<source>Version</source>
<translation type="unfinished">Versión</translation>
</message>
<message>
+ <source>Starting Block</source>
+ <translation type="unfinished">Bloque de inicio</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation type="unfinished">Encabezados sincronizados</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation type="unfinished">Bloques sincronizados</translation>
+ </message>
+ <message>
<source>Last Transaction</source>
<translation type="unfinished">Última transacción</translation>
</message>
<message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation type="unfinished">El Sistema Autónomo mapeado utilizado para la selección diversificada de pares.</translation>
+ </message>
+ <message>
+ <source>Mapped AS</source>
+ <translation type="unfinished">SA Mapeado</translation>
+ </message>
+ <message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
- <translation type="unfinished">Si retransmitimos las direcciones a este peer.</translation>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Si retransmitimos las direcciones a este par.</translation>
</message>
<message>
<source>Address Relay</source>
- <translation type="unfinished">Transimisión de la dirección</translation>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Transmisión de la dirección</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">Número total de direcciones procesadas, excluyendo las descartadas por limitación de tasa</translation>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">El número total de direcciones recibidas desde este par que han sido procesadas (excluyendo las direcciones que han sido desestimadas debido a la limitación de velocidad).</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">El número total de direcciones recibidas desde este par que han sido desestimadas (no procesadas) debido a la limitación de velocidad.</translation>
</message>
<message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">Direcciones procesadas</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">Número total de direcciones descartadas por límite de tasa</translation>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Direcciones con límite de ratio</translation>
</message>
<message>
- <source>Addresses Rate-Limited</source>
- <translation type="unfinished">Direcciones con límite de tasa</translation>
+ <source>User Agent</source>
+ <translation type="unfinished">Agente del usuario</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">Ventana del nodo</translation>
</message>
<message>
<source>Current block height</source>
<translation type="unfinished">Altura del bloque actual</translation>
</message>
<message>
+ <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation type="unfinished">Abra el archivo de registro de depuración %1 del directorio de datos actual. Esto puede tomar unos segundos para archivos de registro grandes.</translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation type="unfinished">Reducir el tamaño de la fuente</translation>
</message>
@@ -1886,8 +3121,7 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
- <translation type="unfinished">El protocolo de red de este par está conectado a través de:
- IPv4, IPv6, Onion, I2P, o CJDNS.</translation>
+ <translation type="unfinished">El protocolo de red de este par está conectado a través de: IPv4, IPv6, Onion, I2P, o CJDNS.</translation>
</message>
<message>
<source>Services</source>
@@ -1895,7 +3129,7 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>Whether the peer requested us to relay transactions.</source>
- <translation type="unfinished">Si el peer nos solicitó que transmitiéramos las transacciones.</translation>
+ <translation type="unfinished">Si el par nos solicitó que transmitiéramos las transacciones.</translation>
</message>
<message>
<source>Wants Tx Relay</source>
@@ -1907,7 +3141,7 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>High Bandwidth</source>
- <translation type="unfinished">banda ancha</translation>
+ <translation type="unfinished">Banda ancha</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1919,12 +3153,76 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
</message>
<message>
<source>Last Block</source>
- <translation type="unfinished">Último Bloque</translation>
+ <translation type="unfinished">Último bloque</translation>
</message>
<message>
<source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
<extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
- <translation type="unfinished">Tiempo transcurrido desde que se recibió de este par una nueva transacción aceptada en nuestro mempool.</translation>
+ <translation type="unfinished">Tiempo transcurrido desde que se recibió de este par una nueva transacción aceptada en nuestra piscina de memoria.</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation type="unfinished">Último envío</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation type="unfinished">Última recepción</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation type="unfinished">Tiempo de ping</translation>
+ </message>
+ <message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation type="unfinished">La duración de un ping actualmente pendiente.</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation type="unfinished">Espera de ping</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation type="unfinished">Ping mínimo</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation type="unfinished">Desplazamiento de tiempo</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation type="unfinished">Hora del último bloque</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation type="unfinished">&amp;Abrir</translation>
+ </message>
+ <message>
+ <source>&amp;Console</source>
+ <translation type="unfinished">&amp;Consola</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation type="unfinished">&amp;Tráfico de Red</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation type="unfinished">Totales</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation type="unfinished">Archivo de registro de depuración</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation type="unfinished">Limpiar consola</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation type="unfinished">Entrada:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation type="unfinished">Salida:</translation>
</message>
<message>
<source>Inbound: initiated by peer</source>
@@ -1978,8 +3276,12 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
<translation type="unfinished">&amp;Desconectar</translation>
</message>
<message>
+ <source>1 &amp;hour</source>
+ <translation type="unfinished">1 &amp;hora</translation>
+ </message>
+ <message>
<source>1 d&amp;ay</source>
- <translation type="unfinished">1 día</translation>
+ <translation type="unfinished">1 &amp;día</translation>
</message>
<message>
<source>1 &amp;week</source>
@@ -1995,10 +3297,22 @@ Si recibe este error, debe solicitar al comerciante que le proporcione un URI co
<translation type="unfinished">&amp;Copiar IP/Mascara de red</translation>
</message>
<message>
+ <source>&amp;Unban</source>
+ <translation type="unfinished">&amp;Desbloquear</translation>
+ </message>
+ <message>
<source>Network activity disabled</source>
<translation type="unfinished">Actividad de red desactivada</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation type="unfinished">Ejecutar comando sin monedero</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation type="unfinished">Ejecutar comando usando monedero «%1»</translation>
+ </message>
+ <message>
<source>Welcome to the %1 RPC console.
Use up and down arrows to navigate history, and %2 to clear screen.
Use %3 and %4 to increase or decrease the font size.
@@ -2012,7 +3326,7 @@ For more information on using this console, type %6.
Utiliza %3 y %4 para aumentar o disminuir el tamaño de la fuente.
Escribe %5 para ver un resumen de los comandos disponibles. Para más información sobre cómo usar esta consola, escribe %6.
-%7AVISO: Los estafadores han estado activos diciendo a los usuarios que escriban comandos aquí, robando el contenido de sus carteras. No uses esta consola sin entender completamente las ramificaciones de un comando.%8</translation>
+%7 AVISO: Los estafadores han estado activos diciendo a los usuarios que escriban comandos aquí, robando el contenido de sus monederos. No uses esta consola sin entender completamente las ramificaciones de un comando.%8</translation>
</message>
<message>
<source>Executing…</source>
@@ -2040,6 +3354,10 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
<translation type="unfinished">De</translation>
</message>
<message>
+ <source>Ban for</source>
+ <translation type="unfinished">Bloqueo para</translation>
+ </message>
+ <message>
<source>Never</source>
<translation type="unfinished">Nunca</translation>
</message>
@@ -2052,7 +3370,7 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
<name>ReceiveCoinsDialog</name>
<message>
<source>&amp;Amount:</source>
- <translation type="unfinished">&amp;Cantidad</translation>
+ <translation type="unfinished">&amp;Importe</translation>
</message>
<message>
<source>&amp;Label:</source>
@@ -2063,10 +3381,50 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
<translation type="unfinished">&amp;Mensaje</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Mensaje opcional para agregar a la solicitud de pago, el cual será mostrado cuando la solicitud esté abierta. Nota: El mensaje no se enviará con el pago a través de la red de Bitcoin.</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation type="unfinished">Etiqueta opcional para asociar con la nueva dirección de recepción.</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation type="unfinished">Usa este formulario para solicitar un pago. Todos los campos son &lt;b&gt;opcionales&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation type="unfinished">Un importe opcional para solicitar. Deje esto vacío o en cero para no solicitar una cantidad específica.</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Etiqueta opcional para asociar con la nueva dirección de recepción (utilizado por ti para identificar una factura). También esta asociado a la solicitud de pago.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation type="unfinished">Mensaje opcional asociado a la solicitud de pago que podría ser presentado al remitente </translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation type="unfinished">&amp;Crear una nueva dirección de recepción</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation type="unfinished">Limpiar todos los campos del formulario.</translation>
+ </message>
+ <message>
<source>Clear</source>
<translation type="unfinished">Limpiar</translation>
</message>
<message>
+ <source>Requested payments history</source>
+ <translation type="unfinished">Historial de pagos solicitados</translation>
+ </message>
+ <message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation type="unfinished">Mostrar la solicitud seleccionada (hace lo mismo que hacer doble clic en una entrada)</translation>
+ </message>
+ <message>
<source>Show</source>
<translation type="unfinished">Mostrar</translation>
</message>
@@ -2096,7 +3454,11 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
</message>
<message>
<source>Copy &amp;amount</source>
- <translation type="unfinished">Copiar &amp;cantidad</translation>
+ <translation type="unfinished">Copiar &amp;importe</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">No se pudo desbloquear el monedero.</translation>
</message>
<message>
<source>Could not generate new %1 address</source>
@@ -2115,7 +3477,7 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
</message>
<message>
<source>Amount:</source>
- <translation type="unfinished">Cantidad:</translation>
+ <translation type="unfinished">Importe:</translation>
</message>
<message>
<source>Label:</source>
@@ -2130,8 +3492,12 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
<translation type="unfinished">Monedero:</translation>
</message>
<message>
+ <source>Copy &amp;URI</source>
+ <translation type="unfinished">Copiar &amp;URI</translation>
+ </message>
+ <message>
<source>Copy &amp;Address</source>
- <translation type="unfinished">Copiar &amp;Dirección</translation>
+ <translation type="unfinished">Copiar &amp;dirección</translation>
</message>
<message>
<source>&amp;Verify</source>
@@ -2139,7 +3505,7 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
</message>
<message>
<source>Verify this address on e.g. a hardware wallet screen</source>
- <translation type="unfinished">Verifica esta dirección en la pantalla de tu billetera fría u otro dispositivo</translation>
+ <translation type="unfinished">Verifica esta dirección en la pantalla de tu monedero frío u otro dispositivo</translation>
</message>
<message>
<source>&amp;Save Image…</source>
@@ -2149,10 +3515,18 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
<source>Payment information</source>
<translation type="unfinished">Información del pago</translation>
</message>
- </context>
+ <message>
+ <source>Request payment to %1</source>
+ <translation type="unfinished">Solicitar pago a %1</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation type="unfinished">Fecha</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">Etiqueta</translation>
</message>
@@ -2164,7 +3538,19 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
<source>(no label)</source>
<translation type="unfinished">(sin etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation type="unfinished">(sin mensaje)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation type="unfinished">(sin importe solicitado)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation type="unfinished">Solicitado</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -2173,7 +3559,7 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
</message>
<message>
<source>Coin Control Features</source>
- <translation type="unfinished">Características de control de la moneda</translation>
+ <translation type="unfinished">Características de control de moneda</translation>
</message>
<message>
<source>automatically selected</source>
@@ -2189,7 +3575,7 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
</message>
<message>
<source>Amount:</source>
- <translation type="unfinished">Cuantía:</translation>
+ <translation type="unfinished">Importe:</translation>
</message>
<message>
<source>Fee:</source>
@@ -2204,32 +3590,80 @@ Escribe %5 para ver un resumen de los comandos disponibles. Para más informaciÃ
<translation type="unfinished">Cambio:</translation>
</message>
<message>
+ <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
+ <translation type="unfinished">Al activarse, si la dirección esta vacía o es inválida, las monedas serán enviadas a una nueva dirección generada.</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation type="unfinished">Dirección de cambio personalizada</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation type="unfinished">Comisión de transacción:</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">Si utilizas la comisión por defecto, la transacción puede tardar varias horas o incluso días (o nunca) en confirmarse. Considera elegir la comisión de forma manual o espera hasta que se haya validado completamente la cadena.</translation>
</message>
<message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation type="unfinished">Advertencia: En este momento no se puede estimar la comisión.</translation>
+ </message>
+ <message>
<source>per kilobyte</source>
<translation type="unfinished">por kilobyte</translation>
</message>
<message>
+ <source>Hide</source>
+ <translation type="unfinished">Ocultar</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation type="unfinished">Recomendado:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation type="unfinished">Personalizado:</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation type="unfinished">Enviar a múltiples destinatarios a la vez</translation>
+ </message>
+ <message>
+ <source>Add &amp;Recipient</source>
+ <translation type="unfinished">Agrega &amp;destinatario</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation type="unfinished">Limpiar todos los campos del formulario.</translation>
+ </message>
+ <message>
<source>Inputs…</source>
<translation type="unfinished">Entradas...</translation>
</message>
<message>
+ <source>Dust:</source>
+ <translation type="unfinished">Polvo:</translation>
+ </message>
+ <message>
<source>Choose…</source>
<translation type="unfinished">Elegir...</translation>
</message>
<message>
<source>Hide transaction fee settings</source>
- <translation type="unfinished">Ocultar ajustes de tarifas de transacción</translation>
+ <translation type="unfinished">Ocultar ajustes de comisión de transacción</translation>
</message>
<message>
<source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
- <translation type="unfinished">Especifica una tarifa personalizada por kB (1.000 bytes) del tamaño virtual de la transacción.
+ <translation type="unfinished">Especifica una comisión personalizada por kB (1.000 bytes) del tamaño virtual de la transacción.
-Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por kvB" para una transacción de 500 bytes virtuales (la mitad de 1 kvB), supondría finalmente una tasa de sólo 50 satoshis.</translation>
+Nota: Dado que la comisión se calcula por cada byte, una tasa de «100 satoshis por kvB» para una transacción de 500 bytes virtuales (la mitad de 1 kvB), supondría finalmente una comisión de sólo 50 satoshis.</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Cuando hay menos volumen de transacciones que espacio en los bloques, los mineros y los nodos de retransmisión pueden imponer una comisión mínima. Pagar solo esta comisión mínima está bien, pero tenga en cuenta que esto puede resultar en una transacción nunca confirmada una vez que haya más demanda de transacciones de Bitcoin de la que la red puede procesar.</translation>
</message>
<message>
<source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
@@ -2240,6 +3674,66 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<translation type="unfinished">(Comisión inteligente no inicializada todavía. Esto normalmente tarda unos pocos bloques…)</translation>
</message>
<message>
+ <source>Confirmation time target:</source>
+ <translation type="unfinished">Objetivo de tiempo de confirmación</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation type="unfinished">Habilitar Replace-By-Fee</translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation type="unfinished">Con Replace-By-Fee (BIP-125) puede incrementar la comisión después de haber enviado la transacción. Si no utiliza esto, se recomienda que añada una comisión mayor para compensar el riesgo adicional de que la transacción se retrase.</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished">Limpiar &amp;todo</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation type="unfinished">Saldo:</translation>
+ </message>
+ <message>
+ <source>Confirm the send action</source>
+ <translation type="unfinished">Confirmar el envío</translation>
+ </message>
+ <message>
+ <source>S&amp;end</source>
+ <translation type="unfinished">&amp;Enviar</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">Copiar cantidad</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">Copiar importe</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Copiar comisión</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Copiar después de la comisión</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">Copiar bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">Copiar polvo</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">Copiar cambio</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation type="unfinished">%1 (%2 bloques)</translation>
+ </message>
+ <message>
<source>Sign on device</source>
<extracomment>"device" usually means a hardware wallet.</extracomment>
<translation type="unfinished">Iniciar sesión en el dispositivo</translation>
@@ -2254,8 +3748,28 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<translation type="unfinished">Configura una ruta externa al script en Opciones -&gt; Monedero</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation type="unfinished">Cr&amp;ear sin firmar</translation>
+ </message>
+ <message>
+ <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
+ <translation type="unfinished">Crea una Transacción de Bitcoin Parcialmente Firmada (TBPF) para uso con p.ej. un monedero fuera de linea %1, o un monedero de hardware compatible con TBPF</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation type="unfinished">desde monedero «%1»</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation type="unfinished">%1 a «%2»</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation type="unfinished">%1 a %2</translation>
+ </message>
+ <message>
<source>To review recipient list click "Show Details…"</source>
- <translation type="unfinished">Para ver la lista de receptores haga clic en "Mostrar detalles"</translation>
+ <translation type="unfinished">Para ver la lista de receptores haga clic en «Mostrar detalles...»</translation>
</message>
<message>
<source>Sign failed</source>
@@ -2282,7 +3796,7 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
</message>
<message>
<source>PSBT saved</source>
- <translation type="unfinished">PSBT guardado </translation>
+ <translation type="unfinished">TBPF guardado </translation>
</message>
<message>
<source>External balance:</source>
@@ -2293,6 +3807,10 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<translation type="unfinished">o</translation>
</message>
<message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation type="unfinished">Puede incrementar la comisión más tarde (use Replace-By-Fee, BIP-125).</translation>
+ </message>
+ <message>
<source>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>
<extracomment>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.</extracomment>
<translation type="unfinished">Por favor, revisa tu propuesta de transacción. Esto producirá una Transacción de Bitcoin Parcialmente Firmada (TBPF) que puedes guardar o copiar y después firmar p.ej. un monedero fuera de línea %1, o un monedero de hardware compatible con TBPF.</translation>
@@ -2300,12 +3818,12 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<message>
<source>Do you want to create this transaction?</source>
<extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
- <translation type="unfinished">Deseas crear esta transacción?</translation>
+ <translation type="unfinished">¿Deseas crear esta transacción?</translation>
</message>
<message>
<source>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>
<extracomment>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.</extracomment>
- <translation type="unfinished">Por favor, revisa tu transacción. Puedes crear y enviar esta transacción o crear una Transacción Bitcoin Parcialmente Firmada (PSBT), que puedes guardar o copiar y luego firmar con, por ejemplo, un monedero %1 offline o un monedero hardware compatible con PSBT.</translation>
+ <translation type="unfinished">Por favor, revisa tu transacción. Puedes crear y enviar esta transacción o crear una Transacción Bitcoin Parcialmente Firmada (TBPF), que puedes guardar o copiar y luego firmar con, por ejemplo, un monedero %1 offline o un monedero hardware compatible con TBPF.</translation>
</message>
<message>
<source>Please, review your transaction.</source>
@@ -2317,17 +3835,73 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<translation type="unfinished">Comisión por transacción.</translation>
</message>
<message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation type="unfinished">No usa Replace-By-Fee, BIP-125.</translation>
+ </message>
+ <message>
<source>Total Amount</source>
- <translation type="unfinished">Cantidad total</translation>
+ <translation type="unfinished">Importe total</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation type="unfinished">Confirmar el envío de monedas</translation>
+ </message>
+ <message>
+ <source>Watch-only balance:</source>
+ <translation type="unfinished">Balance solo observación:</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation type="unfinished">La dirección de envío no es válida. Por favor revísela.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation type="unfinished">El importe a pagar debe ser mayor que 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation type="unfinished">El importe sobrepasa su saldo.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation type="unfinished">El total sobrepasa su saldo cuando se incluye la comisión de envío de %1.</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation type="unfinished">Dirección duplicada encontrada: las direcciones sólo deben ser utilizadas una vez.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation type="unfinished">¡Fallo al crear la transacción!</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation type="unfinished">Una comisión mayor que %1 se considera como una comisión absurdamente alta.</translation>
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Estimado para comenzar confirmación dentro de %n bloque.</numerusform>
+ <numerusform>Estimado para comenzar confirmación dentro de %n bloques.</numerusform>
</translation>
</message>
<message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation type="unfinished">Alerta: Dirección de Bitcoin inválida</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation type="unfinished">Alerta: Dirección de cambio desconocida</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation type="unfinished">Confirmar dirección de cambio personalizada</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">La dirección que ha seleccionado para el cambio no es parte de su monedero. Parte o todos sus fondos pueden ser enviados a esta dirección. ¿Está seguro?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(sin etiqueta)</translation>
</message>
@@ -2335,20 +3909,44 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<context>
<name>SendCoinsEntry</name>
<message>
+ <source>A&amp;mount:</source>
+ <translation type="unfinished">I&amp;mporte:</translation>
+ </message>
+ <message>
+ <source>Pay &amp;To:</source>
+ <translation type="unfinished">Pagar &amp;a:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation type="unfinished">&amp;Etiqueta:</translation>
+ </message>
+ <message>
<source>Choose previously used address</source>
<translation type="unfinished">Escoger una dirección previamente usada</translation>
</message>
<message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation type="unfinished">Dirección Bitcoin a la que se enviará el pago</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation type="unfinished">Pegar dirección desde portapapeles</translation>
+ </message>
+ <message>
<source>Remove this entry</source>
<translation type="unfinished">Quitar esta entrada</translation>
</message>
<message>
<source>The amount to send in the selected unit</source>
- <translation type="unfinished">El monto a enviar en la unidad seleccionada</translation>
+ <translation type="unfinished">El importe a enviar en la unidad seleccionada</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">La comisión será deducida de la cantidad enviada. El destinatario recibirá menos bitcoins que la cantidad introducida en el campo Cantidad. Si hay varios destinatarios seleccionados, la comisión será distribuida a partes iguales.</translation>
+ <translation type="unfinished">La comisión será deducida de la cantidad enviada. El destinatario recibirá menos bitcoins que la cantidad introducida en el campo Importe. Si hay varios destinatarios seleccionados, la comisión será distribuida a partes iguales.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation type="unfinished">S&amp;ustraer comisión del importe.</translation>
</message>
<message>
<source>Use available balance</source>
@@ -2359,26 +3957,14 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<translation type="unfinished">Mensaje:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Esta es una solicitud de pago no autentificada.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Esta es una solicitud de pago autentificada.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
</message>
<message>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
- <translation type="unfinished">Mensaje que se agrgará al URI de Bitcoin, el cuál será almacenado con la transacción para su referencia. Nota: Este mensaje no será mandado a través de la red de Bitcoin.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pagar a:</translation>
+ <translation type="unfinished">Mensaje que se agrgará al URI de Bitcoin, el cuál será almacenado con la transacción para su referencia. Nota: Este mensaje no será enviado a través de la red de Bitcoin.</translation>
</message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -2393,30 +3979,146 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation type="unfinished">Firmas - Firmar / verificar un mensaje</translation>
+ </message>
+ <message>
<source>&amp;Sign Message</source>
- <translation type="unfinished">&amp;Firmar Mensaje</translation>
+ <translation type="unfinished">&amp;Firmar mensaje</translation>
</message>
<message>
<source>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>
<translation type="unfinished">Puedes firmar los mensajes con tus direcciones para demostrar que las posees. Ten cuidado de no firmar cualquier cosa vaga, ya que los ataques de phishing pueden tratar de engañarte firmando tu identidad a través de ellos. Firma solo declaraciones totalmente detalladas con las que estés de acuerdo.</translation>
</message>
<message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation type="unfinished">La dirección Bitcoin con la que se firmó el mensaje</translation>
+ </message>
+ <message>
<source>Choose previously used address</source>
- <translation type="unfinished">Escoger dirección previamente usada</translation>
+ <translation type="unfinished">Escoger una dirección previamente usada</translation>
</message>
<message>
<source>Paste address from clipboard</source>
- <translation type="unfinished">Pega dirección desde portapapeles</translation>
+ <translation type="unfinished">Pegar dirección desde portapapeles</translation>
+ </message>
+ <message>
+ <source>Enter the message you want to sign here</source>
+ <translation type="unfinished">Escribe aquí el mensaje que deseas firmar</translation>
</message>
<message>
<source>Signature</source>
<translation type="unfinished">Firma</translation>
</message>
<message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation type="unfinished">Copiar la firma actual al portapapeles del sistema</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation type="unfinished">Firmar un mensaje para demostrar que se posee una dirección Bitcoin</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation type="unfinished">Firmar &amp;mensaje</translation>
+ </message>
+ <message>
+ <source>Reset all sign message fields</source>
+ <translation type="unfinished">Limpiar todos los campos de la firma de mensaje</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished">Limpiar &amp;todo</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation type="unfinished">&amp;Verificar mensaje</translation>
+ </message>
+ <message>
+ <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
+ <translation type="unfinished">Introduzca la dirección para la firma, el mensaje (asegurándose de copiar tal cual los saltos de línea, espacios, tabulaciones, etc.) y la firma a continuación para verificar el mensaje. Tenga cuidado de no asumir más información de lo que dice el propio mensaje firmado para evitar fraudes basados en ataques de tipo man-in-the-middle. Tenga en cuenta que esto solo prueba que la parte firmante recibe con esta dirección, ¡no puede probar el envío de ninguna transacción!</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation type="unfinished">Dirección Bitcoin con la que firmar el mensaje</translation>
+ </message>
+ <message>
+ <source>The signed message to verify</source>
+ <translation type="unfinished">El mensaje firmado para verificar</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation type="unfinished">La firma proporcionada cuando el mensaje fue firmado</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation type="unfinished">Verifique el mensaje para comprobar que fue firmado con la dirección Bitcoin indicada</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation type="unfinished">Verificar &amp;mensaje</translation>
+ </message>
+ <message>
+ <source>Reset all verify message fields</source>
+ <translation type="unfinished">Limpiar todos los campos de la verificación de mensaje</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation type="unfinished">Haga clic en «Firmar mensaje» para generar la firma</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation type="unfinished">La dirección introducida es inválida</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation type="unfinished">Por favor, revise la dirección e inténtelo nuevamente.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation type="unfinished">La dirección introducida no corresponde a una clave.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation type="unfinished">Se ha cancelado el desbloqueo del monedero. </translation>
+ </message>
+ <message>
+ <source>No error</source>
+ <translation type="unfinished">Sin error </translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation type="unfinished">No se dispone de la clave privada para la dirección introducida.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation type="unfinished">Falló la firma del mensaje.</translation>
+ </message>
+ <message>
<source>Message signed.</source>
<translation type="unfinished">Mensaje firmado.</translation>
</message>
- </context>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation type="unfinished">La firma no pudo decodificarse.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation type="unfinished">Por favor, compruebe la firma e inténtelo de nuevo.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation type="unfinished">La firma no coincide con el resumen del mensaje.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation type="unfinished">Falló la verificación del mensaje.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation type="unfinished">Mensaje verificado.</translation>
+ </message>
+</context>
<context>
<name>SplashScreen</name>
<message>
@@ -2431,6 +4133,40 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<context>
<name>TransactionDesc</name>
<message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
+ <translation type="unfinished">Hay un conflicto con una transacción de %1 confirmaciones.</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/sin confirmar, en la piscina de memoria</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/sin confirmar, no en la piscina de memoria</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
+ <translation type="unfinished">abandonada</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
+ <translation type="unfinished">%1/sin confirmar</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
+ <translation type="unfinished">%1 confirmaciones</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation type="unfinished">Estado</translation>
+ </message>
+ <message>
<source>Date</source>
<translation type="unfinished">Fecha</translation>
</message>
@@ -2443,28 +4179,199 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<translation type="unfinished">Generado</translation>
</message>
<message>
+ <source>From</source>
+ <translation type="unfinished">De</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation type="unfinished">desconocido</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation type="unfinished">Para</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation type="unfinished">dirección propia</translation>
+ </message>
+ <message>
<source>watch-only</source>
<translation type="unfinished">Solo observación</translation>
</message>
+ <message>
+ <source>label</source>
+ <translation type="unfinished">etiqueta</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation type="unfinished">Crédito</translation>
+ </message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>disponible en %n bloque</numerusform>
+ <numerusform>disponible en %n bloques</numerusform>
</translation>
</message>
<message>
+ <source>not accepted</source>
+ <translation type="unfinished">no aceptada</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation type="unfinished">Débito</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation type="unfinished">Total débito</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation type="unfinished">Total crédito</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation type="unfinished">Comisión por transacción.</translation>
</message>
- </context>
+ <message>
+ <source>Net amount</source>
+ <translation type="unfinished">Importe neto</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation type="unfinished">Mensaje</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation type="unfinished">Comentario</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation type="unfinished">ID transacción</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation type="unfinished">Tamaño total transacción</translation>
+ </message>
+ <message>
+ <source>Transaction virtual size</source>
+ <translation type="unfinished">Tamaño virtual transacción</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation type="unfinished">Ãndice de salida</translation>
+ </message>
+ <message>
+ <source> (Certificate was not verified)</source>
+ <translation type="unfinished"> (No se ha verificado el certificado)</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation type="unfinished">Comerciante</translation>
+ </message>
+ <message>
+ <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation type="unfinished">Las monedas generadas deben madurar %1 bloques antes de que puedan ser gastadas. Una vez que generas este bloque, es propagado por la red para ser añadido a la cadena de bloques. Si falla el intento de añadirse en la cadena, su estado cambiará a «no aceptado» y ya no se puede gastar. Esto puede ocurrir ocasionalmente si otro nodo genera un bloque a los pocos segundos del tuyo.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation type="unfinished">Información de depuración</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation type="unfinished">Transacción</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation type="unfinished">Entradas</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Importe</translation>
+ </message>
+ <message>
+ <source>true</source>
+ <translation type="unfinished">verdadero</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation type="unfinished">falso</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDescDialog</name>
+ <message>
+ <source>This pane shows a detailed description of the transaction</source>
+ <translation type="unfinished">Esta ventana muestra información detallada sobre la transacción</translation>
+ </message>
+ <message>
+ <source>Details for %1</source>
+ <translation type="unfinished">Detalles para %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation type="unfinished">Fecha</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation type="unfinished">Tipo</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">Etiqueta</translation>
</message>
<message>
+ <source>Unconfirmed</source>
+ <translation type="unfinished">Sin confirmar</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation type="unfinished">Abandonada</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation type="unfinished">Confirmando (%1 de %2 confirmaciones recomendadas)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation type="unfinished">Confirmada (%1 confirmaciones)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation type="unfinished">En conflicto</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation type="unfinished">No disponible (%1 confirmaciones, disponible después de %2)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation type="unfinished">Generada pero no aceptada</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation type="unfinished">Recibido con</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation type="unfinished">Recibido de</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation type="unfinished">Enviado a</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation type="unfinished">Pago a mi mismo</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation type="unfinished">Minado</translation>
+ </message>
+ <message>
<source>watch-only</source>
<translation type="unfinished">Solo observación</translation>
</message>
@@ -2472,24 +4379,100 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<source>(no label)</source>
<translation type="unfinished">(sin etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation type="unfinished">Estado de transacción. Pasa el ratón sobre este campo para ver el número de confirmaciones.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation type="unfinished">Fecha y hora cuando se recibió la transacción.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation type="unfinished">Tipo de transacción.</translation>
+ </message>
+ <message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation type="unfinished">Si una dirección de solo observación está involucrada en esta transacción o no.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation type="unfinished">Descripción de la transacción definida por el usuario.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation type="unfinished">Importe sustraído o añadido al balance.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation type="unfinished">Todo</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation type="unfinished">Hoy</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation type="unfinished">Esta semana</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation type="unfinished">Este mes</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation type="unfinished">El mes pasado </translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation type="unfinished">Este año</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation type="unfinished">Recibido con</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation type="unfinished">Enviado a</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation type="unfinished">A ti mismo</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation type="unfinished">Minado</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation type="unfinished">Otra</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation type="unfinished">Introduzca dirección, id de transacción o etiqueta a buscar</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation type="unfinished">Importe mínimo</translation>
+ </message>
+ <message>
<source>Range…</source>
<translation type="unfinished">Rango...</translation>
</message>
<message>
<source>&amp;Copy address</source>
- <translation type="unfinished">copiar dirección </translation>
+ <translation type="unfinished">&amp;Copiar dirección</translation>
</message>
<message>
<source>Copy &amp;label</source>
- <translation type="unfinished">copiar y etiquetar </translation>
+ <translation type="unfinished">Copiar &amp;etiqueta</translation>
</message>
<message>
<source>Copy &amp;amount</source>
- <translation type="unfinished">Copiar cantidad</translation>
+ <translation type="unfinished">Copiar &amp;importe</translation>
</message>
<message>
<source>Copy transaction &amp;ID</source>
@@ -2497,27 +4480,27 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
</message>
<message>
<source>Copy &amp;raw transaction</source>
- <translation type="unfinished">Copiar traducción en crudo</translation>
+ <translation type="unfinished">Copiar transacción en c&amp;rudo</translation>
</message>
<message>
<source>Copy full transaction &amp;details</source>
- <translation type="unfinished">Copiar la transacción entera &amp; detalles</translation>
+ <translation type="unfinished">Copiar &amp;detalles completos de la transacción</translation>
</message>
<message>
<source>&amp;Show transaction details</source>
- <translation type="unfinished">Mostrar detalles de la transacción</translation>
+ <translation type="unfinished">&amp;Mostrar detalles de la transacción</translation>
</message>
<message>
<source>Increase transaction &amp;fee</source>
- <translation type="unfinished">Incrementar la comisión de transacción</translation>
+ <translation type="unfinished">&amp;Incrementar comisión de transacción</translation>
</message>
<message>
<source>A&amp;bandon transaction</source>
- <translation type="unfinished">Abandonar transacción</translation>
+ <translation type="unfinished">A&amp;bandonar transacción</translation>
</message>
<message>
<source>&amp;Edit address label</source>
- <translation type="unfinished">Editar etiqueta de dirección</translation>
+ <translation type="unfinished">&amp;Editar etiqueta de dirección</translation>
</message>
<message>
<source>Show in %1</source>
@@ -2525,10 +4508,31 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<translation type="unfinished">Mostrar en %1</translation>
</message>
<message>
+ <source>Export Transaction History</source>
+ <translation type="unfinished">Exportar historial de transacciones</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Archivo separado por comas</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">Confirmado</translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation type="unfinished">Solo observación</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Fecha</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation type="unfinished">Tipo</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">Etiqueta</translation>
</message>
@@ -2540,7 +4544,27 @@ Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por k
<source>Exporting Failed</source>
<translation type="unfinished">La exportación falló</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation type="unfinished">Ha habido un error al intentar guardar en el histórico la transacción con %1.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation type="unfinished">Exportación satisfactoria</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation type="unfinished">El historial de transacciones ha sido guardado exitosamente en %1</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation type="unfinished">Rango:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation type="unfinished">a</translation>
+ </message>
+</context>
<context>
<name>WalletFrame</name>
<message>
@@ -2553,11 +4577,11 @@ Vaya a Archivo&gt; Abrir monedero para cargar un monedero.
</message>
<message>
<source>Create a new wallet</source>
- <translation type="unfinished">Crear monedero nuevo</translation>
+ <translation type="unfinished">Crea un monedero nuevo</translation>
</message>
<message>
<source>Unable to decode PSBT from clipboard (invalid base64)</source>
- <translation type="unfinished">No se puede decodificar PSBT desde el portapapeles (inválido base64)</translation>
+ <translation type="unfinished">No se puede decodificar TBPF desde el portapapeles (inválido base64)</translation>
</message>
<message>
<source>Load Transaction Data</source>
@@ -2569,27 +4593,75 @@ Vaya a Archivo&gt; Abrir monedero para cargar un monedero.
</message>
<message>
<source>PSBT file must be smaller than 100 MiB</source>
- <translation type="unfinished">El archivo PSBT debe ser más pequeño de 100 MiB</translation>
+ <translation type="unfinished">El archivo TBPF debe ser más pequeño de 100 MiB</translation>
</message>
<message>
<source>Unable to decode PSBT</source>
- <translation type="unfinished">Imposible descodificar PSBT</translation>
+ <translation type="unfinished">No es posible descodificar TBPF</translation>
</message>
</context>
<context>
<name>WalletModel</name>
<message>
+ <source>Send Coins</source>
+ <translation type="unfinished">Enviar monedas</translation>
+ </message>
+ <message>
+ <source>Fee bump error</source>
+ <translation type="unfinished">Error de incremento de la comisión</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation type="unfinished">Ha fallado el incremento de la comisión de transacción.</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <extracomment>Asks a user if they would like to manually increase the fee of a transaction that has already been created.</extracomment>
+ <translation type="unfinished">¿Desea incrementar la comisión?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation type="unfinished">Comisión actual:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation type="unfinished">Incremento:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation type="unfinished">Nueva comisión:</translation>
+ </message>
+ <message>
<source>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>
- <translation type="unfinished">Advertencia: Esto puede pagar la tasa adicional al reducir el cambio de salidas o agregar entradas, cuando sea necesario. Puede agregar una nueva salida de cambio si aún no existe. Estos cambios pueden potencialmente filtrar la privacidad.</translation>
+ <translation type="unfinished">Advertencia: Esto puede pagar la comisión adicional al reducir el cambio de salidas o agregar entradas, cuando sea necesario. Puede agregar una nueva salida de cambio si aún no existe. Potencialmente estos cambios pueden comprometer la privacidad.</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation type="unfinished">Confirmar incremento de comisión</translation>
+ </message>
+ <message>
+ <source>Can't draft transaction.</source>
+ <translation type="unfinished">No se pudo preparar la transacción.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation type="unfinished">TBPF copiada </translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation type="unfinished">No se ha podido firmar la transacción.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation type="unfinished">No se pudo confirmar la transacción</translation>
</message>
<message>
<source>Can't display address</source>
- <translation type="unfinished">No se puede mostrar la dirección
-</translation>
+ <translation type="unfinished">No se puede mostrar la dirección</translation>
</message>
<message>
<source>default wallet</source>
- <translation type="unfinished">Monedero predeterminado</translation>
+ <translation type="unfinished">monedero predeterminado</translation>
</message>
</context>
<context>
@@ -2603,9 +4675,33 @@ Vaya a Archivo&gt; Abrir monedero para cargar un monedero.
<translation type="unfinished">Exportar a un archivo los datos de esta pestaña</translation>
</message>
<message>
+ <source>Backup Wallet</source>
+ <translation type="unfinished">Respaldar monedero</translation>
+ </message>
+ <message>
<source>Wallet Data</source>
<extracomment>Name of the wallet data file format.</extracomment>
- <translation type="unfinished">Datos de la billetera </translation>
+ <translation type="unfinished">Datos del monedero </translation>
</message>
- </context>
+ <message>
+ <source>Backup Failed</source>
+ <translation type="unfinished">Copia de seguridad fallida</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation type="unfinished">Ha habido un error al intentar guardar los datos del monedero a %1.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation type="unfinished">Se ha completado con éxito la copia de respaldo</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation type="unfinished">Los datos del monedero se han guardado con éxito en %1.</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation type="unfinished">Cancelar</translation>
+ </message>
+</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts
index f7f8f0e39b..71532b4e21 100644
--- a/src/qt/locale/bitcoin_es_CL.ts
+++ b/src/qt/locale/bitcoin_es_CL.ts
@@ -246,7 +246,7 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
</message>
<message>
<source>Internal error</source>
- <translation type="unfinished">Error interno</translation>
+ <translation type="unfinished">error interno</translation>
</message>
<message>
<source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
@@ -427,10 +427,6 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
<translation type="unfinished">Error al leer la base de datos, cerrando aplicación.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Error actualizando la base de datos chainstate</translation>
- </message>
- <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">Ha fallado la escucha en todos los puertos. Usa -listen=0 si desea esto.</translation>
</message>
@@ -546,10 +542,6 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
<source>Unknown network specified in -onlynet: '%s'</source>
<translation type="unfinished">La red especificada en -onlynet: '%s' es desconocida</translation>
</message>
- <message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Actualizando la base de datos UTXO</translation>
- </message>
</context>
<context>
<name>BitcoinGUI</name>
@@ -1070,6 +1062,27 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Al menos %1 GB de información será almacenado en este directorio, y seguirá creciendo a través del tiempo.</translation>
@@ -1111,10 +1124,6 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
<translation type="unfinished">Como esta es la primera vez que se lanza el programa, puede elegir dónde %1 almacenará sus datos.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Al hacer clic OK, %1 iniciará el proceso de descarga y procesará el blockchain completo de %4 (%2 GB), iniciando desde el la transacción más antigua %3 cuando %4 se ejecutó inicialmente.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">Esta sincronización inicial es muy exigente y puede exponer problemas de hardware con su computadora que anteriormente habían pasado desapercibidos. Cada vez que ejecuta %1, continuará la descarga donde lo dejó.</translation>
</message>
@@ -1372,14 +1381,17 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirmar restablecimiento de opciones</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Se requiere el reinicio del cliente para activar los cambios.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">El cliente será cluasurado. Quieres proceder?</translation>
</message>
<message>
@@ -2115,10 +2127,6 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Una comisión mayor que %1 se considera como una comisión absurda-mente alta.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Solicitud de pago caducada.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2186,21 +2194,9 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
<translation type="unfinished">Mensaje:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Esta es una petición de pago no autentificada.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Esta es una petición de pago autentificada.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pagar a:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -2336,30 +2332,22 @@ Usa el boton "Crear nueva direccion de recibimiento" en la pestaña de recibir p
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">Hay un conflicto con la traducción de las confirmaciones %1</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/no confirmado, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">en el equipo de memoria</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">no en el equipo de memoria</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abandonado</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/no confirmado</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">confirmaciones %1</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_es_CO.ts b/src/qt/locale/bitcoin_es_CO.ts
index 68c53b9651..de80671c8a 100644
--- a/src/qt/locale/bitcoin_es_CO.ts
+++ b/src/qt/locale/bitcoin_es_CO.ts
@@ -420,10 +420,6 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
<translation type="unfinished">Error al leer la base de datos, cerrando aplicación.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Error actualizando la base de datos chainstate</translation>
- </message>
- <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">Ha fallado la escucha en todos los puertos. Usa -listen=0 si desea esto.</translation>
</message>
@@ -539,10 +535,6 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation type="unfinished">La red especificada en -onlynet: '%s' es desconocida</translation>
</message>
- <message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Actualizando la base de datos UTXO</translation>
- </message>
</context>
<context>
<name>BitcoinGUI</name>
@@ -783,6 +775,11 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
<translation type="unfinished">No hay billeteras disponibles</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nombre de la billetera </translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">y windows
</translation>
@@ -1019,6 +1016,11 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
<translation type="unfinished">Crear Billetera</translation>
</message>
<message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">Creación de monedero&lt;b&gt;%1&lt;/b&gt;</translation>
+ </message>
+ <message>
<source>Create wallet failed</source>
<translation type="unfinished">Fallo al crear la billetera</translation>
</message>
@@ -1177,6 +1179,27 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Al menos %1 GB de información será almacenado en este directorio, y seguirá creciendo a través del tiempo.</translation>
@@ -1218,10 +1241,6 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
<translation type="unfinished">Al ser la primera vez que se ejecuta el programa, puede elegir donde %1 almacenará sus datos.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Al hacer clic OK, %1 iniciará el proceso de descarga y procesará el blockchain completo de %4 (%2 GB), iniciando desde el la transacción más antigua %3 cuando %4 se ejecutó inicialmente.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">Revertir esta configuración requiere descargar la blockchain completa nuevamente. Es más rápido descargar la cadena completa y podarla después. Desactiva algunas funciones avanzadas.</translation>
</message>
@@ -1488,14 +1507,17 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirmar reestablecimiento de las opciones</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Es necesario reiniciar el cliente para activar los cambios.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">El cliente se cerrará. Desea proceder?</translation>
</message>
<message>
@@ -2261,10 +2283,6 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Una comisión mayor que %1 se considera como una comisión absurda-mente alta.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Solicitud de pago expirada</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2336,21 +2354,9 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
<translation type="unfinished">Mensaje:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Esta es una petición de pago no autentificada.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Esta es una petición de pago autentificada.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pagar a:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -2490,30 +2496,22 @@ Firmar solo es posible con direcciones del tipo 'Legacy'.</translation>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">Hay un conflicto con la traducción de las confirmaciones %1</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/no confirmado, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">en el equipo de memoria</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">no en el equipo de memoria</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abandonado</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/no confirmado</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">confirmaciones %1</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts
index b46a80e380..bb68bb770b 100644
--- a/src/qt/locale/bitcoin_es_DO.ts
+++ b/src/qt/locale/bitcoin_es_DO.ts
@@ -162,6 +162,14 @@
<translation type="unfinished">Monedero cifrado</translation>
</message>
<message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation type="unfinished">Tu monedero va a ser cifrado</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation type="unfinished">Tu monedero está ahora cifrado</translation>
+ </message>
+ <message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
<translation type="unfinished">IMPORTANTE: Cualquier copia de seguridad que haya realizado previamente de su archivo de monedero debe reemplazarse con el nuevo archivo de monedero cifrado. Por razones de seguridad, las copias de seguridad previas del archivo de monedero no cifradas serán inservibles en cuanto comience a usar el nuevo monedero cifrado.</translation>
</message>
@@ -195,6 +203,13 @@
</message>
</context>
<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">Error interno</translation>
+ </message>
+ </context>
+<context>
<name>QObject</name>
<message>
<source>Error: Specified data directory "%1" does not exist.</source>
@@ -385,6 +400,14 @@
<translation type="unfinished">Mostrar información acerca de Qt</translation>
</message>
<message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Crear monedero nuevo</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">Minimizar</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation type="unfinished">Enviar monedas a una dirección Bitcoin</translation>
</message>
@@ -405,6 +428,10 @@
<translation type="unfinished">&amp;Recibir</translation>
</message>
<message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;Cifrar monedero</translation>
+ </message>
+ <message>
<source>Encrypt the private keys that belong to your wallet</source>
<translation type="unfinished">Encriptar las llaves privadas que pertenecen a tu billetera</translation>
</message>
@@ -699,6 +726,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -861,10 +909,12 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirme el restablecimiento de las opciones</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Reinicio del cliente para activar cambios.</translation>
</message>
<message>
@@ -1342,10 +1392,6 @@
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Paga a:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1466,10 +1512,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/no confirmado</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 confirmaciones</translation>
</message>
<message>
@@ -1754,6 +1802,13 @@
</message>
</context>
<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Crear monedero nuevo</translation>
+ </message>
+ </context>
+<context>
<name>WalletModel</name>
<message>
<source>Send Coins</source>
diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts
deleted file mode 100644
index a8c50616a6..0000000000
--- a/src/qt/locale/bitcoin_es_MX.ts
+++ /dev/null
@@ -1,2478 +0,0 @@
-<TS version="2.1" language="es_MX">
-<context>
- <name>AddressBookPage</name>
- <message>
- <source>Right-click to edit address or label</source>
- <translation type="unfinished">Haga clic derecho para editar la dirección o la etiqueta</translation>
- </message>
- <message>
- <source>Create a new address</source>
- <translation type="unfinished">Crear una nueva dirección</translation>
- </message>
- <message>
- <source>&amp;New</source>
- <translation type="unfinished">&amp;Nuevo</translation>
- </message>
- <message>
- <source>Copy the currently selected address to the system clipboard</source>
- <translation type="unfinished">Copiar la dirección seleccionada al portapapeles del sistema</translation>
- </message>
- <message>
- <source>&amp;Copy</source>
- <translation type="unfinished">&amp;Copiar</translation>
- </message>
- <message>
- <source>C&amp;lose</source>
- <translation type="unfinished">Cerrar</translation>
- </message>
- <message>
- <source>Delete the currently selected address from the list</source>
- <translation type="unfinished">Eliminar la dirección actualmente seleccionada de la lista</translation>
- </message>
- <message>
- <source>Enter address or label to search</source>
- <translation type="unfinished">Ingrese dirección o capa a buscar </translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation type="unfinished">Exportar la información en la pestaña actual a un archivo</translation>
- </message>
- <message>
- <source>&amp;Export</source>
- <translation type="unfinished">&amp;Exportar</translation>
- </message>
- <message>
- <source>&amp;Delete</source>
- <translation type="unfinished">&amp;Borrar</translation>
- </message>
- <message>
- <source>Choose the address to send coins to</source>
- <translation type="unfinished">Elija la direccion a donde se enviaran las monedas</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation type="unfinished">Elija la dirección para recibir monedas.</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation type="unfinished">Elija</translation>
- </message>
- <message>
- <source>Sending addresses</source>
- <translation type="unfinished">Direcciones de Envio</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation type="unfinished">Direcciones de recibo</translation>
- </message>
- <message>
- <source>&amp;Copy Address</source>
- <translation type="unfinished">&amp;Copiar dirección</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation type="unfinished">copiar y etiquetar</translation>
- </message>
- <message>
- <source>&amp;Edit</source>
- <translation type="unfinished">Editar</translation>
- </message>
- <message>
- <source>Export Address List</source>
- <translation type="unfinished">Exportar lista de direcciones </translation>
- </message>
- <message>
- <source>Comma separated file</source>
- <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
- <translation type="unfinished">Archivo separado por comas</translation>
- </message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
- <translation type="unfinished">Hubo un error al tratar de guardar la lista de direcciones a %1. Por favor intente de nuevo.</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation type="unfinished">Exportación Fallida</translation>
- </message>
-</context>
-<context>
- <name>AddressTableModel</name>
- <message>
- <source>Label</source>
- <translation type="unfinished">Etiqueta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation type="unfinished">Dirección</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation type="unfinished">(sin etiqueta)</translation>
- </message>
-</context>
-<context>
- <name>AskPassphraseDialog</name>
- <message>
- <source>Passphrase Dialog</source>
- <translation type="unfinished">Dialogo de contraseña</translation>
- </message>
- <message>
- <source>Enter passphrase</source>
- <translation type="unfinished">Ingrese la contraseña</translation>
- </message>
- <message>
- <source>New passphrase</source>
- <translation type="unfinished">Nueva contraseña</translation>
- </message>
- <message>
- <source>Repeat new passphrase</source>
- <translation type="unfinished">Repita la nueva contraseña</translation>
- </message>
- <message>
- <source>Show passphrase</source>
- <translation type="unfinished">Mostrar contraseña</translation>
- </message>
- <message>
- <source>Encrypt wallet</source>
- <translation type="unfinished">Encriptar cartera</translation>
- </message>
- <message>
- <source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation type="unfinished">Esta operación necesita la contraseña de su cartera para desbloquear su cartera.</translation>
- </message>
- <message>
- <source>Unlock wallet</source>
- <translation type="unfinished">Desbloquear cartera</translation>
- </message>
- <message>
- <source>Change passphrase</source>
- <translation type="unfinished">Cambiar contraseña</translation>
- </message>
- <message>
- <source>Confirm wallet encryption</source>
- <translation type="unfinished">Confirmar la encriptación de cartera</translation>
- </message>
- <message>
- <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished">Advertencia: Si encripta su cartera y pierde su contraseña, &lt;b&gt;PERDERà TODOS SUS BITCOINS&lt;/b&gt;!</translation>
- </message>
- <message>
- <source>Are you sure you wish to encrypt your wallet?</source>
- <translation type="unfinished">¿Está seguro que desea encriptar su cartera?</translation>
- </message>
- <message>
- <source>Wallet encrypted</source>
- <translation type="unfinished">Cartera encriptada</translation>
- </message>
- <message>
- <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">Ingresa la nueva frase contraseña para la billetera &lt;br/&gt;Por favor usa una frase contraseña de &lt;b&gt;diez o mas caracteres aleatorios &lt;/b&gt;, o &lt;b&gt;ocho o mas palabras&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Enter the old passphrase and new passphrase for the wallet.</source>
- <translation type="unfinished">Ingresa la antigua frase de contraseña y la nueva frase de contraseña para la billetera.</translation>
- </message>
- <message>
- <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation type="unfinished">Recuerda que encriptar tu billetera no protege completamente tus bitcoins contra robo por malware que haya infectado tu computadora.</translation>
- </message>
- <message>
- <source>Wallet to be encrypted</source>
- <translation type="unfinished">Billetera para ser encriptada</translation>
- </message>
- <message>
- <source>Your wallet is about to be encrypted. </source>
- <translation type="unfinished">Tu billetera está por ser encriptada</translation>
- </message>
- <message>
- <source>Your wallet is now encrypted. </source>
- <translation type="unfinished">Tu billetera ha sido encriptada</translation>
- </message>
- <message>
- <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation type="unfinished">IMPORTANTE: Cualquier copia de seguridad anterior que haya hecho de su archivo de cartera debe ser reemplazada por el archivo de cartera recién generado y encriptado. Por razones de seguridad, las copias de seguridad anteriores del archivo de cartera sin cifrar serán inútiles tan pronto como empieces a usar la nueva billetera encriptada.</translation>
- </message>
- <message>
- <source>Wallet encryption failed</source>
- <translation type="unfinished">Encriptación de la cartera fallida</translation>
- </message>
- <message>
- <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation type="unfinished">La encriptación de la cartera falló debido a un error interno. Su cartera no fue encriptada.</translation>
- </message>
- <message>
- <source>The supplied passphrases do not match.</source>
- <translation type="unfinished">Las contraseñas dadas no coinciden.</translation>
- </message>
- <message>
- <source>Wallet unlock failed</source>
- <translation type="unfinished">El desbloqueo de la cartera falló.</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation type="unfinished">La contraseña ingresada para la desencriptación de la cartera es incorrecta.</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation type="unfinished">La contraseña del monedero se cambió correctamente.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation type="unfinished">Advertencia: ¡La tecla Bloq Mayus está activada!</translation>
- </message>
-</context>
-<context>
- <name>BanTableModel</name>
- <message>
- <source>IP/Netmask</source>
- <translation type="unfinished">IP/Máscara de red</translation>
- </message>
- <message>
- <source>Banned Until</source>
- <translation type="unfinished">Prohibido Hasta</translation>
- </message>
-</context>
-<context>
- <name>BitcoinApplication</name>
- <message>
- <source>Runaway exception</source>
- <translation type="unfinished">Excepción fuera de control</translation>
- </message>
- <message>
- <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <translation type="unfinished">Ha ocurrido un error grave. %1 no puede continuar de forma segura y se cerrará.</translation>
- </message>
- <message>
- <source>Internal error</source>
- <translation type="unfinished">Error interno</translation>
- </message>
- <message>
- <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <translation type="unfinished">Un error interno ocurrió. %1 intentará continuar. Este es un error inesperado que puede ser reportado de las formas que se muestran debajo.</translation>
- </message>
-</context>
-<context>
- <name>QObject</name>
- <message>
- <source>%1 didn't yet exit safely…</source>
- <translation type="unfinished">%1 todavía no ha terminado de forma segura...</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation type="unfinished">desconocido</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation type="unfinished">Monto</translation>
- </message>
- <message>
- <source>Unroutable</source>
- <translation type="unfinished">No se puede enrutar</translation>
- </message>
- <message>
- <source>Internal</source>
- <translation type="unfinished">Interno</translation>
- </message>
- <message>
- <source>Inbound</source>
- <extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
- <translation type="unfinished">Entrada</translation>
- </message>
- <message>
- <source>Outbound</source>
- <extracomment>An outbound connection to a peer. An outbound connection is a connection initiated by us.</extracomment>
- <translation type="unfinished">Salida</translation>
- </message>
- <message>
- <source>Full Relay</source>
- <extracomment>Peer connection type that relays all network information.</extracomment>
- <translation type="unfinished">Transmisión completa</translation>
- </message>
- <message>
- <source>Block Relay</source>
- <extracomment>Peer connection type that relays network information about blocks and not transactions or addresses.</extracomment>
- <translation type="unfinished">Relé de bloque</translation>
- </message>
- <message>
- <source>Feeler</source>
- <extracomment>Short-lived peer connection type that tests the aliveness of known addresses.</extracomment>
- <translation type="unfinished">Sensor</translation>
- </message>
- <message>
- <source>Address Fetch</source>
- <extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
- <translation type="unfinished">Búsqueda de dirección</translation>
- </message>
- <message numerus="yes">
- <source>%n second(s)</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message numerus="yes">
- <source>%n minute(s)</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message numerus="yes">
- <source>%n hour(s)</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message numerus="yes">
- <source>%n day(s)</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message numerus="yes">
- <source>%n week(s)</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message numerus="yes">
- <source>%n year(s)</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- </context>
-<context>
- <name>bitcoin-core</name>
- <message>
- <source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
- <translation type="unfinished">No se pudo cambiar la versión %i a la versión anterior %i. Versión del monedero sin cambios.</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">No es posible actualizar un monedero no HD de la versión%i a la versión %isin actualizar para admitir el keypool pre divido. Por favor use la versión %i o no una versión no especificada.</translation>
- </message>
- <message>
- <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">El archivo %s ya existe. Si estás seguro de que esto es lo que quieres, muévelo primero.</translation>
- </message>
- <message>
- <source>No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
- <translation type="unfinished">Ningún archivo de billetera proveído. Para usar createfromdump, -format=&lt;format&gt;debe ser proveído.</translation>
- </message>
- <message>
- <source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation type="unfinished">La cantidad de la transacción es demasiado pequeña para enviarla después de que se haya deducido la tarifa</translation>
- </message>
- <message>
- <source>This is the transaction fee you may pay when fee estimates are not available.</source>
- <translation type="unfinished">Esta es la tarifa de transacción que puede pagar cuando no se dispone de estimaciones de tarifas.</translation>
- </message>
- <message>
- <source>Done loading</source>
- <translation type="unfinished">Carga completa</translation>
- </message>
- <message>
- <source>Error creating %s</source>
- <translation type="unfinished">Error creando %s</translation>
- </message>
- <message>
- <source>Error reading from database, shutting down.</source>
- <translation type="unfinished">Error de lectura de la base de datos, apagando.</translation>
- </message>
- <message>
- <source>Error reading next record from wallet database</source>
- <translation type="unfinished">Error leyendo el siguiente registro de la base de datos de la billetera</translation>
- </message>
- <message>
- <source>Error: Couldn't create cursor into database</source>
- <translation type="unfinished">Error: No se pudo crear el cursor en la base de datos</translation>
- </message>
- <message>
- <source>Error: Got key that was not hex: %s</source>
- <translation type="unfinished">Error: Se recibió una llave que no es hex: %s</translation>
- </message>
- <message>
- <source>Error: Got value that was not hex: %s</source>
- <translation type="unfinished">Error: Se recibió un valor que no es hex: %s</translation>
- </message>
- <message>
- <source>Error: Missing checksum</source>
- <translation type="unfinished">Error: No se ha encontrado 'checksum'</translation>
- </message>
- <message>
- <source>Error: No %s addresses available.</source>
- <translation type="unfinished">Error: No hay %sdirecciones disponibles,</translation>
- </message>
- <message>
- <source>Error: Unable to write record to new wallet</source>
- <translation type="unfinished">Error: No se pudo escribir el registro en la nueva billetera</translation>
- </message>
- <message>
- <source>Failed to rescan the wallet during initialization</source>
- <translation type="unfinished">Falló al volver a escanear la cartera durante la inicialización</translation>
- </message>
- <message>
- <source>Failed to verify database</source>
- <translation type="unfinished">No se pudo verificar la base de datos</translation>
- </message>
- <message>
- <source>Importing…</source>
- <translation type="unfinished">Importando...</translation>
- </message>
- <message>
- <source>Insufficient funds</source>
- <translation type="unfinished">Fondos insuficientes</translation>
- </message>
- <message>
- <source>Invalid -i2psam address or hostname: '%s'</source>
- <translation type="unfinished">Dirección de -i2psam o dominio ' %s' inválido</translation>
- </message>
- <message>
- <source>Loading P2P addresses…</source>
- <translation type="unfinished">Cargando direcciones P2P...</translation>
- </message>
- <message>
- <source>Loading banlist…</source>
- <translation type="unfinished">Cargando banlist...</translation>
- </message>
- <message>
- <source>Loading block index…</source>
- <translation type="unfinished">Cargando el índice de bloques...</translation>
- </message>
- <message>
- <source>Loading wallet…</source>
- <translation type="unfinished">Cargando monedero...</translation>
- </message>
- <message>
- <source>Not enough file descriptors available.</source>
- <translation type="unfinished">No hay suficientes descriptores de archivos disponibles.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">El modo recorte es incompatible con -coinstatsindex.</translation>
- </message>
- <message>
- <source>Pruning blockstore…</source>
- <translation type="unfinished">Podando blockstore...</translation>
- </message>
- <message>
- <source>Replaying blocks…</source>
- <translation type="unfinished">Reproduciendo bloques...</translation>
- </message>
- <message>
- <source>Rescanning…</source>
- <translation type="unfinished">Volviendo a escanear...</translation>
- </message>
- <message>
- <source>Signing transaction failed</source>
- <translation type="unfinished">La transacción de firma falló</translation>
- </message>
- <message>
- <source>Starting network threads…</source>
- <translation type="unfinished">Iniciando procesos de red...</translation>
- </message>
- <message>
- <source>The specified config file %s does not exist</source>
- <translation type="unfinished">El archivo de configuración especificado %s no existe </translation>
- </message>
- <message>
- <source>The transaction amount is too small to pay the fee</source>
- <translation type="unfinished">El monto de la transacción es demasiado pequeño para pagar la tarifa</translation>
- </message>
- <message>
- <source>This is experimental software.</source>
- <translation type="unfinished">Este es un software experimental.</translation>
- </message>
- <message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation type="unfinished">Esta es la tarifa de transacción mínima que se paga en cada transacción.</translation>
- </message>
- <message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation type="unfinished">Esta es la tarifa de transacción que pagará si envía una transacción.</translation>
- </message>
- <message>
- <source>Transaction amount too small</source>
- <translation type="unfinished">El monto de la transacción es demasiado pequeño</translation>
- </message>
- <message>
- <source>Transaction amounts must not be negative</source>
- <translation type="unfinished">Los montos de las transacciones no deben ser negativos</translation>
- </message>
- <message>
- <source>Transaction must have at least one recipient</source>
- <translation type="unfinished">La transacción debe tener al menos un destinatario</translation>
- </message>
- <message>
- <source>Transaction too large</source>
- <translation type="unfinished">La transacción es demasiado grande</translation>
- </message>
- <message>
- <source>Unable to generate initial keys</source>
- <translation type="unfinished">Incapaz de generar claves iniciales</translation>
- </message>
- <message>
- <source>Unable to generate keys</source>
- <translation type="unfinished">Incapaz de generar claves</translation>
- </message>
- <message>
- <source>Unable to open %s for writing</source>
- <translation type="unfinished">No se ha podido abrir %s para escribir</translation>
- </message>
- <message>
- <source>Unknown new rules activated (versionbit %i)</source>
- <translation type="unfinished">Nuevas reglas desconocidas activadas (versionbit %i)</translation>
- </message>
- <message>
- <source>Verifying blocks…</source>
- <translation type="unfinished">Verificando bloques...</translation>
- </message>
- <message>
- <source>Verifying wallet(s)…</source>
- <translation type="unfinished">Verificando wallet(s)...</translation>
- </message>
- </context>
-<context>
- <name>BitcoinGUI</name>
- <message>
- <source>&amp;Overview</source>
- <translation type="unfinished">&amp;Vista previa</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation type="unfinished">Mostrar la vista previa general de la cartera</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation type="unfinished">&amp;Transacciones</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation type="unfinished">Explorar el historial de transacciones</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation type="unfinished">S&amp;alir</translation>
- </message>
- <message>
- <source>Quit application</source>
- <translation type="unfinished">Salir de la aplicación</translation>
- </message>
- <message>
- <source>&amp;About %1</source>
- <translation type="unfinished">&amp;Acerca de %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation type="unfinished">Mostrar información acerca de %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation type="unfinished">Acerca de &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation type="unfinished">Mostrar información acerca de Qt</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation type="unfinished">Modificar las opciones de configuración para %1</translation>
- </message>
- <message>
- <source>Create a new wallet</source>
- <translation type="unfinished">Crear una nueva cartera</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation type="unfinished">Cartera:</translation>
- </message>
- <message>
- <source>Network activity disabled.</source>
- <extracomment>A substring of the tooltip.</extracomment>
- <translation type="unfinished">Actividad de red deshabilitada.</translation>
- </message>
- <message>
- <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation type="unfinished">El proxy está &lt;b&gt;habilitado&lt;/b&gt;: %1</translation>
- </message>
- <message>
- <source>Send coins to a Bitcoin address</source>
- <translation type="unfinished">Enviar monedas a una dirección Bitcoin</translation>
- </message>
- <message>
- <source>Backup wallet to another location</source>
- <translation type="unfinished">Respaldar cartera en otra ubicación</translation>
- </message>
- <message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation type="unfinished">Cambiar la contraseña usada para la encriptación de la cartera</translation>
- </message>
- <message>
- <source>&amp;Send</source>
- <translation type="unfinished">&amp;Enviar</translation>
- </message>
- <message>
- <source>&amp;Receive</source>
- <translation type="unfinished">&amp;Recibir</translation>
- </message>
- <message>
- <source>&amp;Options…</source>
- <translation type="unfinished">&amp;Opciones…</translation>
- </message>
- <message>
- <source>&amp;Encrypt Wallet…</source>
- <translation type="unfinished">&amp;Encriptar billetera…</translation>
- </message>
- <message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation type="unfinished">Cifre las claves privadas que pertenecen a su billetera</translation>
- </message>
- <message>
- <source>&amp;Backup Wallet…</source>
- <translation type="unfinished">&amp;Realizar copia de seguridad de la billetera</translation>
- </message>
- <message>
- <source>&amp;Change Passphrase…</source>
- <translation type="unfinished">&amp;Cambiar contraseña...</translation>
- </message>
- <message>
- <source>Sign &amp;message…</source>
- <translation type="unfinished">Firmar &amp;mensaje...</translation>
- </message>
- <message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Firme mensajes con sus direcciones de Bitcoin para demostrar que los posee</translation>
- </message>
- <message>
- <source>&amp;Verify message…</source>
- <translation type="unfinished">&amp;Verificar mensaje...</translation>
- </message>
- <message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation type="unfinished">Verifique los mensajes para asegurarse de que se firmaron con direcciones de Bitcoin especificadas.</translation>
- </message>
- <message>
- <source>&amp;Load PSBT from file…</source>
- <translation type="unfinished">&amp;Cargar PSBT desde el archivo...</translation>
- </message>
- <message>
- <source>Open &amp;URI…</source>
- <translation type="unfinished">Abrir &amp;URI…</translation>
- </message>
- <message>
- <source>Close Wallet…</source>
- <translation type="unfinished">Cerrar Billetera</translation>
- </message>
- <message>
- <source>Create Wallet…</source>
- <translation type="unfinished">Crear Billetera</translation>
- </message>
- <message>
- <source>Close All Wallets…</source>
- <translation type="unfinished">Cerrar todas las carteras</translation>
- </message>
- <message>
- <source>&amp;File</source>
- <translation type="unfinished">&amp;Archivo</translation>
- </message>
- <message>
- <source>&amp;Settings</source>
- <translation type="unfinished">&amp;Configuraciones</translation>
- </message>
- <message>
- <source>&amp;Help</source>
- <translation type="unfinished">&amp;Ayuda</translation>
- </message>
- <message>
- <source>Tabs toolbar</source>
- <translation type="unfinished">Pestañas</translation>
- </message>
- <message>
- <source>Syncing Headers (%1%)…</source>
- <translation type="unfinished">Sincronizando cabeceras (%1%) ...</translation>
- </message>
- <message>
- <source>Synchronizing with network…</source>
- <translation type="unfinished">Sincronizando con la red...</translation>
- </message>
- <message>
- <source>Indexing blocks on disk…</source>
- <translation type="unfinished">Indexando bloques en disco...</translation>
- </message>
- <message>
- <source>Processing blocks on disk…</source>
- <translation type="unfinished">Procesando bloques en disco...</translation>
- </message>
- <message>
- <source>Reindexing blocks on disk…</source>
- <translation type="unfinished">Reindexando bloques en disco...</translation>
- </message>
- <message>
- <source>Connecting to peers…</source>
- <translation type="unfinished">Conectando a pares...</translation>
- </message>
- <message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation type="unfinished"> 
-Solicitar pagos (genera códigos QR y bitcoin: URI)
- </translation>
- </message>
- <message>
- <source>Show the list of used sending addresses and labels</source>
- <translation type="unfinished">Mostrar la lista de direcciones y etiquetas de envío usadas</translation>
- </message>
- <message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation type="unfinished">Mostrar la lista de direcciones y etiquetas de recepción usadas</translation>
- </message>
- <message>
- <source>&amp;Command-line options</source>
- <translation type="unfinished">opciones de la &amp;Linea de comandos</translation>
- </message>
- <message numerus="yes">
- <source>Processed %n block(s) of transaction history.</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message>
- <source>Catching up…</source>
- <translation type="unfinished">Poniéndose al día...</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation type="unfinished">Las transacciones después de esto todavía no serán visibles.</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation type="unfinished">Aviso</translation>
- </message>
- <message>
- <source>Information</source>
- <translation type="unfinished">Información </translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation type="unfinished">Actualizado al dia </translation>
- </message>
- <message>
- <source>Open Wallet</source>
- <translation type="unfinished">Abrir Cartera</translation>
- </message>
- <message>
- <source>Open a wallet</source>
- <translation type="unfinished">Abrir una cartera</translation>
- </message>
- <message>
- <source>Close wallet</source>
- <translation type="unfinished">Cerrar cartera</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation type="unfinished">cartera predeterminada</translation>
- </message>
- <message>
- <source>No wallets available</source>
- <translation type="unfinished">No hay carteras disponibles</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation type="unfinished">&amp;Ventana</translation>
- </message>
- <message>
- <source>Main Window</source>
- <translation type="unfinished">Ventana Principal</translation>
- </message>
- <message numerus="yes">
- <source>%n active connection(s) to Bitcoin network.</source>
- <extracomment>A substring of the tooltip.</extracomment>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message>
- <source>Click for more actions.</source>
- <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
- <translation type="unfinished">Haz click para ver más acciones.</translation>
- </message>
- <message>
- <source>Show Peers tab</source>
- <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
- <translation type="unfinished">Mostrar pestaña Pares</translation>
- </message>
- <message>
- <source>Disable network activity</source>
- <extracomment>A context menu item.</extracomment>
- <translation type="unfinished">Desactivar actividad de la red</translation>
- </message>
- <message>
- <source>Enable network activity</source>
- <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
- <translation type="unfinished">Activar actividad de la red</translation>
- </message>
- <message>
- <source>Warning: %1</source>
- <translation type="unfinished">Alerta: %1</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation type="unfinished">Fecha: %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation type="unfinished">Monto: %1
-</translation>
- </message>
- <message>
- <source>Wallet: %1
-</source>
- <translation type="unfinished">Cartera: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation type="unfinished">Tipo: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation type="unfinished">Etiqueta: %1
-</translation>
- </message>
- <message>
- <source>Address: %1
-</source>
- <translation type="unfinished">Dirección: %1
-</translation>
- </message>
- <message>
- <source>Sent transaction</source>
- <translation type="unfinished">Enviar Transacción</translation>
- </message>
- <message>
- <source>Incoming transaction</source>
- <translation type="unfinished">Transacción entrante</translation>
- </message>
- <message>
- <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation type="unfinished">Clave privada &lt;b&gt;desactivada&lt;/b&gt;</translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation type="unfinished">La cartera esta &lt;b&gt;encriptada&lt;/b&gt; y &lt;b&gt;desbloqueada&lt;/b&gt; actualmente </translation>
- </message>
- <message>
- <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation type="unfinished">La cartera esta &lt;b&gt;encriptada&lt;/b&gt; y &lt;b&gt;bloqueada&lt;/b&gt; actualmente </translation>
- </message>
- </context>
-<context>
- <name>CoinControlDialog</name>
- <message>
- <source>Coin Selection</source>
- <translation type="unfinished">Selección de moneda</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation type="unfinished">Cantidad</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation type="unfinished">Monto:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation type="unfinished">Cuota:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation type="unfinished">Remanente monetario:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation type="unfinished">Después de los cargos por comisión. </translation>
- </message>
- <message>
- <source>Change:</source>
- <translation type="unfinished">Cambio</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation type="unfinished">(De)seleccionar todo</translation>
- </message>
- <message>
- <source>Tree mode</source>
- <translation type="unfinished">Modo árbol </translation>
- </message>
- <message>
- <source>List mode</source>
- <translation type="unfinished">Modo lista </translation>
- </message>
- <message>
- <source>Amount</source>
- <translation type="unfinished">Monto</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation type="unfinished">Recibido con etiqueta</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation type="unfinished">recibido con dirección</translation>
- </message>
- <message>
- <source>Date</source>
- <translation type="unfinished">Fecha</translation>
- </message>
- <message>
- <source>Confirmations</source>
- <translation type="unfinished">Confirmaciones</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation type="unfinished">Confirmado </translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation type="unfinished">copiar monto</translation>
- </message>
- <message>
- <source>&amp;Copy address</source>
- <translation type="unfinished">&amp;Copiar dirección</translation>
- </message>
- <message>
- <source>Copy &amp;label</source>
- <translation type="unfinished">Copiar &amp;label</translation>
- </message>
- <message>
- <source>Copy &amp;amount</source>
- <translation type="unfinished">Copiar &amp;amount</translation>
- </message>
- <message>
- <source>L&amp;ock unspent</source>
- <translation type="unfinished">Bloquear no gastado</translation>
- </message>
- <message>
- <source>&amp;Unlock unspent</source>
- <translation type="unfinished">&amp;Desbloquear lo no gastado</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation type="unfinished">Copiar cantidad</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation type="unfinished">Copiar cuota</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation type="unfinished">Copiar después de cuota</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation type="unfinished">Copiar bytes</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation type="unfinished">Copiar cambio</translation>
- </message>
- <message>
- <source>yes</source>
- <translation type="unfinished">si</translation>
- </message>
- <message>
- <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation type="unfinished">Esta capa se vuelve roja si algún destinatario recibe un monto menor al actual limite del remanente monetario </translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation type="unfinished">Puede variar +/- %1 satoshi(s) por entrada.</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation type="unfinished">(sin etiqueta)</translation>
- </message>
- <message>
- <source>(change)</source>
- <translation type="unfinished">(cambio)</translation>
- </message>
-</context>
-<context>
- <name>CreateWalletActivity</name>
- <message>
- <source>Create Wallet</source>
- <extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
- <translation type="unfinished">Crear una cartera </translation>
- </message>
- <message>
- <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
- <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
- <translation type="unfinished">Creando Monedero &lt;b&gt;%1&lt;/b&gt;…</translation>
- </message>
- <message>
- <source>Create wallet failed</source>
- <translation type="unfinished">La creación de la cartera falló</translation>
- </message>
- <message>
- <source>Create wallet warning</source>
- <translation type="unfinished">Crear advertencia de cartera</translation>
- </message>
- <message>
- <source>Can't list signers</source>
- <translation type="unfinished">No se pueden listar los firmantes</translation>
- </message>
-</context>
-<context>
- <name>OpenWalletActivity</name>
- <message>
- <source>Open wallet failed</source>
- <translation type="unfinished">Abrir la cartera falló</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation type="unfinished">cartera predeterminada</translation>
- </message>
- <message>
- <source>Open Wallet</source>
- <extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
- <translation type="unfinished">Abrir Cartera</translation>
- </message>
- <message>
- <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
- <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
- <translation type="unfinished">Abriendo billetera &lt;b&gt;%1&lt;/b&gt;...</translation>
- </message>
-</context>
-<context>
- <name>WalletController</name>
- <message>
- <source>Close wallet</source>
- <translation type="unfinished">Cerrar cartera</translation>
- </message>
- <message>
- <source>Close all wallets</source>
- <translation type="unfinished">Cerrar todas las carteras</translation>
- </message>
- <message>
- <source>Are you sure you wish to close all wallets?</source>
- <translation type="unfinished">¿Está seguro de cerrar todas las carteras?</translation>
- </message>
-</context>
-<context>
- <name>CreateWalletDialog</name>
- <message>
- <source>Create Wallet</source>
- <translation type="unfinished">Crear una cartera </translation>
- </message>
- <message>
- <source>Wallet Name</source>
- <translation type="unfinished">Nombre de la cartera </translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation type="unfinished">Cartera</translation>
- </message>
- <message>
- <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
- <translation type="unfinished">Encriptar la cartera. La cartera será encriptada con una frase de contraseña de tu elección.</translation>
- </message>
- <message>
- <source>Encrypt Wallet</source>
- <translation type="unfinished">Encripta la cartera</translation>
- </message>
- <message>
- <source>Advanced Options</source>
- <translation type="unfinished">Opciones avanzadas</translation>
- </message>
- <message>
- <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">Desactivar las llaves privadas de esta cartera. Las carteras con las llaves privadas desactivadas no tendrán llaves privadas y no podrán tener una semilla HD o llaves privadas importadas. Esto es ideal para las carteras "watch-only".</translation>
- </message>
- <message>
- <source>Disable Private Keys</source>
- <translation type="unfinished">Desactivar las claves privadas</translation>
- </message>
- <message>
- <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
- <translation type="unfinished">Utilice un dispositivo de firma externo, como un monedero de hardware. Configure primero el script del firmante externo en las preferencias del monedero.</translation>
- </message>
- <message>
- <source>External signer</source>
- <translation type="unfinished">firmante externo</translation>
- </message>
- <message>
- <source>Create</source>
- <translation type="unfinished">Crear</translation>
- </message>
- <message>
- <source>Compiled without external signing support (required for external signing)</source>
- <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Compilado sin soporte de firma externa (necesario para la firma externa)</translation>
- </message>
-</context>
-<context>
- <name>EditAddressDialog</name>
- <message>
- <source>Edit Address</source>
- <translation type="unfinished">Editar dirección</translation>
- </message>
- <message>
- <source>&amp;Label</source>
- <translation type="unfinished">&amp;Etiqueta</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation type="unfinished">La etiqueta asociada a esta entrada de la lista de direcciones</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation type="unfinished">La dirección asociada a esta entrada de la lista de direcciones. Esto sólo puede ser modificado para las direcciones de envío.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation type="unfinished">&amp;Dirección</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation type="unfinished">Nueva dirección de envío</translation>
- </message>
- <message>
- <source>Edit receiving address</source>
- <translation type="unfinished">Editar dirección de recepción</translation>
- </message>
- <message>
- <source>Edit sending address</source>
- <translation type="unfinished">Editar dirección de envío</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation type="unfinished">No se puede desbloquear la cartera</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation type="unfinished">La generación de la nueva clave fallo</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation type="unfinished">Un nuevo directorio de datos será creado.</translation>
- </message>
- <message>
- <source>name</source>
- <translation type="unfinished">nombre</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation type="unfinished">El camino ya existe, y no es un directorio.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation type="unfinished">No se puede crear un directorio de datos aquí.</translation>
- </message>
-</context>
-<context>
- <name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(de los %1 GB necesarios)</translation>
- </message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB necesarios para la cadena completa)</translation>
- </message>
- <message numerus="yes">
- <source>(sufficient to restore backups %n day(s) old)</source>
- <extracomment>Explanatory text on the capability of the current prune target.</extracomment>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation type="unfinished">La cartera también se almacenará en este directorio.</translation>
- </message>
- <message>
- <source>Welcome</source>
- <translation type="unfinished">Bienvenido</translation>
- </message>
- <message>
- <source>Limit block chain storage to</source>
- <translation type="unfinished">Limitar el almacenamiento de cadena de bloque a</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Revertir esta configuración requiere descargar nuevamente la cadena de bloques en su totalidad. es mas eficaz descargar la cadena de bloques completa y después reducirla. Desabilitará algunas funciones avanzadas.</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">La sincronización inicial es muy demandante, por lo que algunos problemas en su equipo de computo que no hayan sido detectados pueden verse reflejados. Cada vez que corra al %1, continuará descargando donde se le dejó.</translation>
- </message>
- <message>
- <source>Use the default data directory</source>
- <translation type="unfinished">Usar el directorio de datos predeterminado</translation>
- </message>
- <message>
- <source>Use a custom data directory:</source>
- <translation type="unfinished">Usar un directorio de datos customizado:</translation>
- </message>
-</context>
-<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation type="unfinished">versión</translation>
- </message>
- <message>
- <source>Command-line options</source>
- <translation type="unfinished">opciones de la Linea de comandos</translation>
- </message>
-</context>
-<context>
- <name>ShutdownWindow</name>
- <message>
- <source>%1 is shutting down…</source>
- <translation type="unfinished">%1 se está cerrando...</translation>
- </message>
- <message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation type="unfinished">No apague su computadora hasta que esta ventana desaparesca.</translation>
- </message>
-</context>
-<context>
- <name>ModalOverlay</name>
- <message>
- <source>Form</source>
- <translation type="unfinished">Formulario</translation>
- </message>
- <message>
- <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation type="unfinished">Las transacciones recientes pueden no ser visibles todavía, y por lo tanto el saldo de su cartera podría ser incorrecto. Esta información será correcta una vez que su cartera haya terminado de sincronizarse con la red de bitcoin, como se detalla abajo.</translation>
- </message>
- <message>
- <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation type="unfinished">Los intentos de gastar bitcoins que se vean afectados por transacciones aún no mostradas no serán aceptados por la red.</translation>
- </message>
- <message>
- <source>Number of blocks left</source>
- <translation type="unfinished">Número de bloques restantes</translation>
- </message>
- <message>
- <source>Unknown…</source>
- <translation type="unfinished">Desconocido...</translation>
- </message>
- <message>
- <source>calculating…</source>
- <translation type="unfinished">calculando...</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation type="unfinished">Progreso </translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation type="unfinished">Aumento del progreso por hora</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation type="unfinished">Tiempo estimado restante hasta la sincronización</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation type="unfinished">Ocultar </translation>
- </message>
- <message>
- <source>Unknown. Syncing Headers (%1, %2%)…</source>
- <translation type="unfinished">Desconocido. Sincronizando Cabeceras (%1, %2%)…</translation>
- </message>
-</context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Open bitcoin URI</source>
- <translation type="unfinished">Abrir la URI de bitcoin</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <extracomment>Tooltip text for button that allows you to paste an address that is in your clipboard.</extracomment>
- <translation type="unfinished">Pegar dirección del portapapeles</translation>
- </message>
-</context>
-<context>
- <name>OptionsDialog</name>
- <message>
- <source>Options</source>
- <translation type="unfinished">Opciones</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Activar el pruning reduce significativamente el espacio de disco necesario para guardar las transacciones. Todos los bloques son completamente validados de cualquier manera. Revertir esta opción requiere que descarques de nuevo toda la cadena de bloques.</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Minimizar en lugar de salir de la aplicación cuando la ventana se cierra. Cuando esta opción está activada, la aplicación se cerrará sólo después de seleccionar Salir en el menú.</translation>
- </message>
- <message>
- <source>Open Configuration File</source>
- <translation type="unfinished">Abrir Configuración de Archivo</translation>
- </message>
- <message>
- <source>W&amp;allet</source>
- <translation type="unfinished">Cartera</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Si usted desactiva el gasto de cambio no confirmado, el cambio de una transacción no puede ser utilizado hasta que esa transacción tenga al menos una confirmación. Esto también afecta la manera en que se calcula su saldo.</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation type="unfinished">&amp;Gastar el cambio no confirmado</translation>
- </message>
- <message>
- <source>External Signer (e.g. hardware wallet)</source>
- <translation type="unfinished">Dispositivo Externo de Firma (ej. billetera de hardware)</translation>
- </message>
- <message>
- <source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
- <translation type="unfinished">Ruta completa al script compatible con Bitcoin Core (ej. C:\Descargas\hwi.exe o /Usuarios/SuUsuario/Descargas/hwi.py). Cuidado: código malicioso podría robarle sus monedas!</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Abre el puerto del cliente de Bitcoin en el router automáticamente. Esto solo funciona cuando el router soporta NAT-PMP y está habilitado. El puerto externo podría ser elegido al azar.</translation>
- </message>
- <message>
- <source>Map port using NA&amp;T-PMP</source>
- <translation type="unfinished">Mapear el puerto usando NA&amp;T-PMP</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation type="unfinished">Aceptar las conexiones del exterior.</translation>
- </message>
- <message>
- <source>&amp;Window</source>
- <translation type="unfinished">&amp;Ventana</translation>
- </message>
- <message>
- <source>Show the icon in the system tray.</source>
- <translation type="unfinished">Mostrar el ícono en la bandeja del sistema.</translation>
- </message>
- <message>
- <source>&amp;Show tray icon</source>
- <translation type="unfinished">Mostrar la bandeja del sistema.</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation type="unfinished">Idioma de la interfaz de usuario:</translation>
- </message>
- <message>
- <source>Monospaced font in the Overview tab:</source>
- <translation type="unfinished">letra Monospace en la pestaña Resumen: </translation>
- </message>
- <message>
- <source>embedded "%1"</source>
- <translation type="unfinished">incrustado "%1"</translation>
- </message>
- <message>
- <source>closest matching "%1"</source>
- <translation type="unfinished">coincidencia más aproximada "%1"</translation>
- </message>
- <message>
- <source>Compiled without external signing support (required for external signing)</source>
- <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Compilado sin soporte de firma externa (necesario para la firma externa)</translation>
- </message>
- <message>
- <source>none</source>
- <translation type="unfinished">Ninguno </translation>
- </message>
- <message>
- <source>This change would require a client restart.</source>
- <translation type="unfinished">Este cambio requeriría un reinicio del cliente.</translation>
- </message>
- </context>
-<context>
- <name>OverviewPage</name>
- <message>
- <source>Form</source>
- <translation type="unfinished">Formulario</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation type="unfinished">&lt;b&gt;Transacciones recientes&lt;/b&gt;</translation>
- </message>
- </context>
-<context>
- <name>PSBTOperationsDialog</name>
- <message>
- <source>Save…</source>
- <translation type="unfinished">Guardar...</translation>
- </message>
- <message>
- <source>Partially Signed Transaction (Binary)</source>
- <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
- <translation type="unfinished">Transacción parcialmente firmada (binario) </translation>
- </message>
- <message>
- <source>Total Amount</source>
- <translation type="unfinished">Cantidad total</translation>
- </message>
- <message>
- <source>or</source>
- <translation type="unfinished">o</translation>
- </message>
- </context>
-<context>
- <name>PaymentServer</name>
- <message>
- <source>Cannot process payment request because BIP70 is not supported.
-Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
-If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
- <translation type="unfinished">No se pudo procesar la solicitud de pago porque BIP70 no es compatible.
-Debido a fallos de seguridad en BIP70, se recomienda ignorar cualquier instrucción sobre cambiar carteras
-Si recibe este error, debe solicitar al vendedor un URI compatible con BIP21.</translation>
- </message>
- </context>
-<context>
- <name>PeerTableModel</name>
- <message>
- <source>Peer</source>
- <extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
- <translation type="unfinished">Par</translation>
- </message>
- <message>
- <source>Sent</source>
- <extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
- <translation type="unfinished">Enviado</translation>
- </message>
- <message>
- <source>Received</source>
- <extracomment>Title of Peers Table column which indicates the total amount of network information we have received from the peer.</extracomment>
- <translation type="unfinished">Recibido</translation>
- </message>
- <message>
- <source>Address</source>
- <extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
- <translation type="unfinished">Dirección</translation>
- </message>
- <message>
- <source>Type</source>
- <extracomment>Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</extracomment>
- <translation type="unfinished">Tipo</translation>
- </message>
- <message>
- <source>Network</source>
- <extracomment>Title of Peers Table column which states the network the peer connected through.</extracomment>
- <translation type="unfinished">Red</translation>
- </message>
- <message>
- <source>Inbound</source>
- <extracomment>An Inbound Connection from a Peer.</extracomment>
- <translation type="unfinished">Entrada</translation>
- </message>
- <message>
- <source>Outbound</source>
- <extracomment>An Outbound Connection to a Peer.</extracomment>
- <translation type="unfinished">Salida</translation>
- </message>
-</context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Save Image…</source>
- <translation type="unfinished">&amp;Guardar imagen</translation>
- </message>
- <message>
- <source>&amp;Copy Image</source>
- <translation type="unfinished">&amp;Copiar Imagen</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation type="unfinished">Error codificando la URI en el Código QR.</translation>
- </message>
- <message>
- <source>QR code support not available.</source>
- <translation type="unfinished">El soporte del código QR no está disponible.</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation type="unfinished">Guardar Código QR</translation>
- </message>
- <message>
- <source>PNG Image</source>
- <extracomment>Expanded name of the PNG file format. See: https://en.wikipedia.org/wiki/Portable_Network_Graphics.</extracomment>
- <translation type="unfinished">Imagen PNG</translation>
- </message>
-</context>
-<context>
- <name>RPCConsole</name>
- <message>
- <source>Client version</source>
- <translation type="unfinished">Versión cliente </translation>
- </message>
- <message>
- <source>&amp;Information</source>
- <translation type="unfinished">&amp;Información</translation>
- </message>
- <message>
- <source>Network</source>
- <translation type="unfinished">Red</translation>
- </message>
- <message>
- <source>Name</source>
- <translation type="unfinished">Nombre</translation>
- </message>
- <message>
- <source>Wallet: </source>
- <translation type="unfinished">Cartera:</translation>
- </message>
- <message>
- <source>(none)</source>
- <translation type="unfinished">(ninguno)</translation>
- </message>
- <message>
- <source>Received</source>
- <translation type="unfinished">Recibido</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation type="unfinished">Enviado</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation type="unfinished">Reducir el tamaño de la letra</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation type="unfinished">Aumentar el tamaño de la letra</translation>
- </message>
- <message>
- <source>The direction and type of peer connection: %1</source>
- <translation type="unfinished">Dirección y tipo de conexión entre pares: %1</translation>
- </message>
- <message>
- <source>Direction/Type</source>
- <translation type="unfinished">Dirección/Tipo</translation>
- </message>
- <message>
- <source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
- <translation type="unfinished">Este par está conectado mediante alguno de los siguientes protocolos de red : IPv4, IPv6, Onion, I2P, or CJDNS.</translation>
- </message>
- <message>
- <source>Services</source>
- <translation type="unfinished">Servicios</translation>
- </message>
- <message>
- <source>Whether the peer requested us to relay transactions.</source>
- <translation type="unfinished">Si el peer nos solicitó que transmitiéramos las transacciones.</translation>
- </message>
- <message>
- <source>Wants Tx Relay</source>
- <translation type="unfinished">Desea una transmisión de transacción</translation>
- </message>
- <message>
- <source>High bandwidth BIP152 compact block relay: %1</source>
- <translation type="unfinished">Transmisión de bloque compacto BIP152 banbda ancha: %1</translation>
- </message>
- <message>
- <source>High Bandwidth</source>
- <translation type="unfinished">banda ancha</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation type="unfinished">Tiempo de conexión</translation>
- </message>
- <message>
- <source>Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
- <translation type="unfinished">Tiempo transcurrido desde que se recibió de este par un nuevo bloque que superó las comprobaciones de validez iniciales.</translation>
- </message>
- <message>
- <source>Last Block</source>
- <translation type="unfinished">Último Bloque</translation>
- </message>
- <message>
- <source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
- <extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
- <translation type="unfinished">Tiempo transcurrido desde que se recibió de este par una nueva transacción aceptada en nuestro mempool.</translation>
- </message>
- <message>
- <source>Last Send</source>
- <translation type="unfinished">Último envío</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation type="unfinished">Última recepción</translation>
- </message>
- <message>
- <source>Inbound: initiated by peer</source>
- <extracomment>Explanatory text for an inbound peer connection.</extracomment>
- <translation type="unfinished">Entrante: iniciado por el par</translation>
- </message>
- <message>
- <source>Outbound Full Relay: default</source>
- <extracomment>Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</extracomment>
- <translation type="unfinished">Relé Completo de Salida: predeterminado</translation>
- </message>
- <message>
- <source>Outbound Block Relay: does not relay transactions or addresses</source>
- <extracomment>Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</extracomment>
- <translation type="unfinished">Retransmisión de bloque saliente: no retransmite transacciones o direcciones</translation>
- </message>
- <message>
- <source>Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
- <extracomment>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.</extracomment>
- <translation type="unfinished">Manual de Salida: agregado usando las opciones de configuración RPC %1 o %2/%3</translation>
- </message>
- <message>
- <source>Outbound Feeler: short-lived, for testing addresses</source>
- <extracomment>Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</extracomment>
- <translation type="unfinished">Sensor de Salida: de corta duración, para probar direcciones</translation>
- </message>
- <message>
- <source>Outbound Address Fetch: short-lived, for soliciting addresses</source>
- <extracomment>Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</extracomment>
- <translation type="unfinished">Recuperación de Dirección Saliente: de corta duración, para solicitar direcciones</translation>
- </message>
- <message>
- <source>we selected the peer for high bandwidth relay</source>
- <translation type="unfinished">hemos seleccionado el par para la retransmisión de banda ancha</translation>
- </message>
- <message>
- <source>the peer selected us for high bandwidth relay</source>
- <translation type="unfinished">El par nos ha seleccionado para transmisión de banda ancha</translation>
- </message>
- <message>
- <source>no high bandwidth relay selected</source>
- <translation type="unfinished">Ninguna transmisión de banda ancha seleccionada</translation>
- </message>
- <message>
- <source>&amp;Copy address</source>
- <extracomment>Context menu action to copy the address of a peer.</extracomment>
- <translation type="unfinished">&amp;Copiar dirección</translation>
- </message>
- <message>
- <source>1 d&amp;ay</source>
- <translation type="unfinished">1 día</translation>
- </message>
- <message>
- <source>Network activity disabled</source>
- <translation type="unfinished">Actividad de la red desactivada</translation>
- </message>
- <message>
- <source>Executing command without any wallet</source>
- <translation type="unfinished">Ejecutando el comando sin ninguna cartera</translation>
- </message>
- <message>
- <source>Welcome to the %1 RPC console.
-Use up and down arrows to navigate history, and %2 to clear screen.
-Use %3 and %4 to increase or decrease the font size.
-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>
- <extracomment>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.</extracomment>
- <translation type="unfinished">Bienvenido a la %1 consola RPC.
-Utilice la flecha arriba y abajo para navegar el historial y %2 para limpiar la consola.
-Utilice%3 y %4 para aumentar o reducir el tamaño de fuente.
-Escriba %5 para una visión general de los comandos disponibles.
-Para obtener más información, escriba %6.
-
-%7ADVERTENCIA: Los estafadores, de forma activa, han estado indicando a los usuarios que escriban comandos aquí y de esta manera roban el contenido de sus monederos. No utilice esta consola si no comprende perfectamente las ramificaciones de un comando.%8</translation>
- </message>
- <message>
- <source>Executing…</source>
- <extracomment>A console message indicating an entered command is currently being executed.</extracomment>
- <translation type="unfinished">Ejecutando...</translation>
- </message>
- <message>
- <source>(peer: %1)</source>
- <translation type="unfinished">(par: %1)</translation>
- </message>
- <message>
- <source>Yes</source>
- <translation type="unfinished">Sí</translation>
- </message>
- <message>
- <source>To</source>
- <translation type="unfinished">Para</translation>
- </message>
- <message>
- <source>From</source>
- <translation type="unfinished">De</translation>
- </message>
- <message>
- <source>Never</source>
- <translation type="unfinished">Nunca</translation>
- </message>
- <message>
- <source>Unknown</source>
- <translation type="unfinished">Desconocido</translation>
- </message>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>&amp;Amount:</source>
- <translation type="unfinished">Monto:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation type="unfinished">&amp;Etiqueta</translation>
- </message>
- <message>
- <source>&amp;Message:</source>
- <translation type="unfinished">Mensaje:</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Mensaje opcional para agregar a la solicitud de pago, el cual será mostrado cuando la solicitud este abierta. Nota: El mensaje no se manda con el pago a travéz de la red de Bitcoin.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation type="unfinished">Una etiqueta opcional para asociar a la nueva dirección de recepción.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation type="unfinished">Use este formulario para la solicitud de pagos. Todos los campos son &lt;b&gt;opcionales&lt;/b&gt;</translation>
- </message>
- <message>
- <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation type="unfinished">Monto opcional a solicitar. Dejarlo vacion o en cero no solicita un monto especifico.</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Una etiqueta opcional para asociar a la nueva dirección de recepción (utilizada por usted para identificar una factura). También se adjunta a la solicitud de pago.</translation>
- </message>
- <message>
- <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
- <translation type="unfinished">Un mensaje opcional que se adjunta a la solicitud de pago y que puede mostrarse al remitente.</translation>
- </message>
- <message>
- <source>&amp;Create new receiving address</source>
- <translation type="unfinished">&amp;Crear una nueva dirección de recepción</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation type="unfinished">Borrar todos los campos del formulario.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation type="unfinished">Borrar </translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation type="unfinished">Historial de pagos solicitados</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation type="unfinished">Mostrar la solicitud seleccionada (hace lo mismo que hacer doble clic en una entrada)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation type="unfinished">Mostrar</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation type="unfinished">Eliminar las entradas seleccionadas de la lista</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation type="unfinished">Eliminar </translation>
- </message>
- <message>
- <source>&amp;Copy address</source>
- <translation type="unfinished">&amp;Copiar dirección</translation>
- </message>
- <message>
- <source>Copy &amp;label</source>
- <translation type="unfinished">Copiar &amp;label</translation>
- </message>
- <message>
- <source>Copy &amp;message</source>
- <translation type="unfinished">Copiar &amp;mensaje</translation>
- </message>
- <message>
- <source>Copy &amp;amount</source>
- <translation type="unfinished">Copiar &amp;amount</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation type="unfinished">No se puede desbloquear la cartera</translation>
- </message>
- </context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Request payment to …</source>
- <translation type="unfinished">Solicitar pago a...</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation type="unfinished">Monto:</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation type="unfinished">Mensaje:</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation type="unfinished">Cartera:</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation type="unfinished">&amp;Copiar dirección</translation>
- </message>
- <message>
- <source>&amp;Verify</source>
- <translation type="unfinished">&amp;Verificar</translation>
- </message>
- <message>
- <source>Verify this address on e.g. a hardware wallet screen</source>
- <translation type="unfinished">Verifique esta dirección en la pantalla de su billetera fría u otro dispositivo</translation>
- </message>
- <message>
- <source>&amp;Save Image…</source>
- <translation type="unfinished">&amp;Guardar imagen</translation>
- </message>
- </context>
-<context>
- <name>RecentRequestsTableModel</name>
- <message>
- <source>Date</source>
- <translation type="unfinished">Fecha</translation>
- </message>
- <message>
- <source>Label</source>
- <translation type="unfinished">Etiqueta</translation>
- </message>
- <message>
- <source>Message</source>
- <translation type="unfinished">Mensaje</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation type="unfinished">(sin etiqueta)</translation>
- </message>
- </context>
-<context>
- <name>SendCoinsDialog</name>
- <message>
- <source>Send Coins</source>
- <translation type="unfinished">Enviar monedas</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation type="unfinished">Cantidad</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation type="unfinished">Monto:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation type="unfinished">Cuota:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation type="unfinished">Después de los cargos por comisión. </translation>
- </message>
- <message>
- <source>Change:</source>
- <translation type="unfinished">Cambio</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation type="unfinished">Ocultar </translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation type="unfinished">Enviar a múltiples receptores a la vez</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation type="unfinished">Borrar todos los campos del formulario.</translation>
- </message>
- <message>
- <source>Inputs…</source>
- <translation type="unfinished">Entradas...</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation type="unfinished">Remanente monetario:</translation>
- </message>
- <message>
- <source>Choose…</source>
- <translation type="unfinished">Elegir...</translation>
- </message>
- <message>
- <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
-
-Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
- <translation type="unfinished">Especifique una tarifa personalizada por kB (1.000 bytes) del tamaño virtual de la transacción.
-
-Nota: Dado que la tasa se calcula por cada byte, una tasa de "100 satoshis por kvB" para una transacción de 500 bytes virtuales (la mitad de 1 kvB) supondría finalmente una tasa de sólo 50 satoshis.</translation>
- </message>
- <message>
- <source>(Smart fee not initialized yet. This usually takes a few blocks…)</source>
- <translation type="unfinished">(Comisión inteligente no inicializada todavía. Usualmente esto tarda algunos bloques…)</translation>
- </message>
- <message>
- <source>Balance:</source>
- <translation type="unfinished">Saldo:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation type="unfinished">Confirme la acción de enviar</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation type="unfinished">Copiar cantidad</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation type="unfinished">copiar monto</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation type="unfinished">Copiar cuota</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation type="unfinished">Copiar después de cuota</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation type="unfinished">Copiar bytes</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation type="unfinished">Copiar cambio</translation>
- </message>
- <message>
- <source>Sign on device</source>
- <extracomment>"device" usually means a hardware wallet.</extracomment>
- <translation type="unfinished">Iniciar sesión en el dispositivo</translation>
- </message>
- <message>
- <source>Connect your hardware wallet first.</source>
- <translation type="unfinished">Conecte su wallet externo primero.</translation>
- </message>
- <message>
- <source>Set external signer script path in Options -&gt; Wallet</source>
- <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Configure una ruta externa al script en Opciones -&gt; Wallet</translation>
- </message>
- <message>
- <source>To review recipient list click "Show Details…"</source>
- <translation type="unfinished">Para revisar la lista de recipientes clique en "Mostrar Detalles..."</translation>
- </message>
- <message>
- <source>Sign failed</source>
- <translation type="unfinished">Falló Firma</translation>
- </message>
- <message>
- <source>External signer not found</source>
- <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Dispositivo externo de firma no encontrado</translation>
- </message>
- <message>
- <source>External signer failure</source>
- <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Fallo en cartera hardware externa </translation>
- </message>
- <message>
- <source>Partially Signed Transaction (Binary)</source>
- <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
- <translation type="unfinished">Transacción parcialmente firmada (binario) </translation>
- </message>
- <message>
- <source>External balance:</source>
- <translation type="unfinished">Saldo externo:</translation>
- </message>
- <message>
- <source>or</source>
- <translation type="unfinished">o</translation>
- </message>
- <message>
- <source>Please, review your transaction.</source>
- <extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
- <translation type="unfinished">Por favor, revise su transacción.</translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation type="unfinished">Cuota de transacción</translation>
- </message>
- <message>
- <source>Total Amount</source>
- <translation type="unfinished">Cantidad total</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation type="unfinished">Confirme para enviar monedas</translation>
- </message>
- <message>
- <source>The recipient address is not valid. Please recheck.</source>
- <translation type="unfinished">La dirección del destinatario no es válida. Por favor, vuelva a verificarla.</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation type="unfinished">El monto a pagar debe ser mayor a 0</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation type="unfinished">La cantidad excede su saldo.</translation>
- </message>
- <message>
- <source>Duplicate address found: addresses should only be used once each.</source>
- <translation type="unfinished">Duplicado de la dirección encontrada: las direcciones sólo deben ser utilizadas una vez cada una.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation type="unfinished">¡La creación de la transación falló!</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">La solicitud de pago expiró.</translation>
- </message>
- <message numerus="yes">
- <source>Estimated to begin confirmation within %n block(s).</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message>
- <source>Warning: Invalid Bitcoin address</source>
- <translation type="unfinished">Advertencia: Dirección de Bitcoin invalida</translation>
- </message>
- <message>
- <source>Warning: Unknown change address</source>
- <translation type="unfinished">Advertencia: Cambio de dirección desconocido</translation>
- </message>
- <message>
- <source>Confirm custom change address</source>
- <translation type="unfinished">Confirmar la dirección de cambio personalizada</translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation type="unfinished">(sin etiqueta)</translation>
- </message>
-</context>
-<context>
- <name>SendCoinsEntry</name>
- <message>
- <source>A&amp;mount:</source>
- <translation type="unfinished">M&amp;onto</translation>
- </message>
- <message>
- <source>Pay &amp;To:</source>
- <translation type="unfinished">Pagar &amp;a:</translation>
- </message>
- <message>
- <source>&amp;Label:</source>
- <translation type="unfinished">&amp;Etiqueta</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation type="unfinished">Elegir la dirección utilizada anteriormente</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation type="unfinished">La dirección de Bitcoin para enviar el pago a</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation type="unfinished">Pegar dirección del portapapeles</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation type="unfinished">Quitar esta entrada</translation>
- </message>
- <message>
- <source>Use available balance</source>
- <translation type="unfinished">Usar el saldo disponible</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation type="unfinished">Mensaje:</translation>
- </message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Esta es una solicitud de pago no autentificada.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Esta es una solicitud de pago autentificada.</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation type="unfinished">Introducir una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pago para:</translation>
- </message>
- </context>
-<context>
- <name>SendConfirmationDialog</name>
- <message>
- <source>Send</source>
- <translation type="unfinished">Enviar</translation>
- </message>
- </context>
-<context>
- <name>SignVerifyMessageDialog</name>
- <message>
- <source>Choose previously used address</source>
- <translation type="unfinished">Elegir la dirección utilizada anteriormente</translation>
- </message>
- <message>
- <source>Paste address from clipboard</source>
- <translation type="unfinished">Pegar dirección del portapapeles</translation>
- </message>
- <message>
- <source>Signature</source>
- <translation type="unfinished">Firma</translation>
- </message>
- <message>
- <source>Message verified.</source>
- <translation type="unfinished">Mensaje verificado.</translation>
- </message>
-</context>
-<context>
- <name>TransactionDesc</name>
- <message>
- <source>%1/unconfirmed</source>
- <translation type="unfinished">%1/No confirmado</translation>
- </message>
- <message>
- <source>%1 confirmations</source>
- <translation type="unfinished">%1 confirmaciones</translation>
- </message>
- <message>
- <source>Status</source>
- <translation type="unfinished">Estado</translation>
- </message>
- <message>
- <source>Date</source>
- <translation type="unfinished">Fecha</translation>
- </message>
- <message>
- <source>From</source>
- <translation type="unfinished">De</translation>
- </message>
- <message>
- <source>unknown</source>
- <translation type="unfinished">desconocido</translation>
- </message>
- <message>
- <source>To</source>
- <translation type="unfinished">Para</translation>
- </message>
- <message>
- <source>label</source>
- <translation type="unfinished">etiqueta</translation>
- </message>
- <message numerus="yes">
- <source>matures in %n more block(s)</source>
- <translation type="unfinished">
- <numerusform />
- <numerusform />
- </translation>
- </message>
- <message>
- <source>Transaction fee</source>
- <translation type="unfinished">Cuota de transacción</translation>
- </message>
- <message>
- <source>Message</source>
- <translation type="unfinished">Mensaje</translation>
- </message>
- <message>
- <source>Comment</source>
- <translation type="unfinished">Comentario</translation>
- </message>
- <message>
- <source>Transaction ID</source>
- <translation type="unfinished">ID</translation>
- </message>
- <message>
- <source>Transaction</source>
- <translation type="unfinished">Transacción</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation type="unfinished">Monto</translation>
- </message>
- </context>
-<context>
- <name>TransactionDescDialog</name>
- <message>
- <source>This pane shows a detailed description of the transaction</source>
- <translation type="unfinished">Este panel muestras una descripción detallada de la transacción</translation>
- </message>
- </context>
-<context>
- <name>TransactionTableModel</name>
- <message>
- <source>Date</source>
- <translation type="unfinished">Fecha</translation>
- </message>
- <message>
- <source>Type</source>
- <translation type="unfinished">Tipo</translation>
- </message>
- <message>
- <source>Label</source>
- <translation type="unfinished">Etiqueta</translation>
- </message>
- <message>
- <source>Confirmed (%1 confirmations)</source>
- <translation type="unfinished">Confimado (%1 confirmaciones)</translation>
- </message>
- <message>
- <source>Generated but not accepted</source>
- <translation type="unfinished">Generado pero no aprovado</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation type="unfinished">Recibido con</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation type="unfinished">Enviar a</translation>
- </message>
- <message>
- <source>Payment to yourself</source>
- <translation type="unfinished">Pagar a si mismo</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation type="unfinished">Minado </translation>
- </message>
- <message>
- <source>(no label)</source>
- <translation type="unfinished">(sin etiqueta)</translation>
- </message>
- <message>
- <source>Date and time that the transaction was received.</source>
- <translation type="unfinished">Fecha y hora en que la transacción fue recibida </translation>
- </message>
- <message>
- <source>Type of transaction.</source>
- <translation type="unfinished">Escriba una transacción</translation>
- </message>
- <message>
- <source>Amount removed from or added to balance.</source>
- <translation type="unfinished">Cantidad removida del saldo o agregada </translation>
- </message>
-</context>
-<context>
- <name>TransactionView</name>
- <message>
- <source>All</source>
- <translation type="unfinished">Todo</translation>
- </message>
- <message>
- <source>Today</source>
- <translation type="unfinished">Hoy</translation>
- </message>
- <message>
- <source>This week</source>
- <translation type="unfinished">Esta semana </translation>
- </message>
- <message>
- <source>This month</source>
- <translation type="unfinished">Este mes </translation>
- </message>
- <message>
- <source>Last month</source>
- <translation type="unfinished">El mes pasado </translation>
- </message>
- <message>
- <source>This year</source>
- <translation type="unfinished">Este año</translation>
- </message>
- <message>
- <source>Received with</source>
- <translation type="unfinished">Recibido con</translation>
- </message>
- <message>
- <source>Sent to</source>
- <translation type="unfinished">Enviar a</translation>
- </message>
- <message>
- <source>To yourself</source>
- <translation type="unfinished">Para ti mismo</translation>
- </message>
- <message>
- <source>Mined</source>
- <translation type="unfinished">Minado </translation>
- </message>
- <message>
- <source>Other</source>
- <translation type="unfinished">Otro</translation>
- </message>
- <message>
- <source>Min amount</source>
- <translation type="unfinished">Monto minimo </translation>
- </message>
- <message>
- <source>Range…</source>
- <translation type="unfinished">Rango...</translation>
- </message>
- <message>
- <source>&amp;Copy address</source>
- <translation type="unfinished">&amp;Copiar dirección</translation>
- </message>
- <message>
- <source>Copy &amp;label</source>
- <translation type="unfinished">Copiar &amp;label</translation>
- </message>
- <message>
- <source>Copy &amp;amount</source>
- <translation type="unfinished">Copiar &amp;amount</translation>
- </message>
- <message>
- <source>Copy transaction &amp;ID</source>
- <translation type="unfinished">Copiar &amp;ID de la transacción</translation>
- </message>
- <message>
- <source>Copy &amp;raw transaction</source>
- <translation type="unfinished">Copiar transacción bruta</translation>
- </message>
- <message>
- <source>Copy full transaction &amp;details</source>
- <translation type="unfinished">Copiar la transacción entera &amp;detalles</translation>
- </message>
- <message>
- <source>&amp;Show transaction details</source>
- <translation type="unfinished">Mostrar detalles de la transacción</translation>
- </message>
- <message>
- <source>Increase transaction &amp;fee</source>
- <translation type="unfinished">Incrementar cuota de transacción</translation>
- </message>
- <message>
- <source>A&amp;bandon transaction</source>
- <translation type="unfinished">Abandonar transacción</translation>
- </message>
- <message>
- <source>&amp;Edit address label</source>
- <translation type="unfinished">Editar etiqueta de dirección</translation>
- </message>
- <message>
- <source>Export Transaction History</source>
- <translation type="unfinished">Exportar el historial de transacción</translation>
- </message>
- <message>
- <source>Comma separated file</source>
- <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
- <translation type="unfinished">Archivo separado por comas</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation type="unfinished">Confirmado </translation>
- </message>
- <message>
- <source>Date</source>
- <translation type="unfinished">Fecha</translation>
- </message>
- <message>
- <source>Type</source>
- <translation type="unfinished">Tipo</translation>
- </message>
- <message>
- <source>Label</source>
- <translation type="unfinished">Etiqueta</translation>
- </message>
- <message>
- <source>Address</source>
- <translation type="unfinished">Dirección</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation type="unfinished">Exportación Fallida</translation>
- </message>
- <message>
- <source>There was an error trying to save the transaction history to %1.</source>
- <translation type="unfinished">Ocurrio un error intentando guardar el historial de transaciones a %1</translation>
- </message>
- <message>
- <source>Exporting Successful</source>
- <translation type="unfinished">Exportacion satisfactoria</translation>
- </message>
- <message>
- <source>The transaction history was successfully saved to %1.</source>
- <translation type="unfinished">el historial de transaciones ha sido guardado exitosamente en %1</translation>
- </message>
- <message>
- <source>to</source>
- <translation type="unfinished">Para</translation>
- </message>
-</context>
-<context>
- <name>WalletFrame</name>
- <message>
- <source>Create a new wallet</source>
- <translation type="unfinished">Crear una nueva cartera</translation>
- </message>
- </context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation type="unfinished">Enviar monedas</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Advertencia: Puede pagar la tasa adicional reduciendo las salidas de cambio o añadiendo entradas, cuando sea necesario. Puede añadir una nueva salida de cambio si no existe ya una. Estos cambios pueden filtrar potencialmente la privacidad.</translation>
- </message>
- <message>
- <source>Can't display address</source>
- <translation type="unfinished">No se puede mostrar la dirección</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation type="unfinished">cartera predeterminada</translation>
- </message>
-</context>
-<context>
- <name>WalletView</name>
- <message>
- <source>&amp;Export</source>
- <translation type="unfinished">&amp;Exportar</translation>
- </message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation type="unfinished">Exportar la información en la pestaña actual a un archivo</translation>
- </message>
- <message>
- <source>Wallet Data</source>
- <extracomment>Name of the wallet data file format.</extracomment>
- <translation type="unfinished">Datos de la billetera </translation>
- </message>
- <message>
- <source>There was an error trying to save the wallet data to %1.</source>
- <translation type="unfinished">Ocurrio un error tratando de guardar la información de la cartera %1</translation>
- </message>
- <message>
- <source>The wallet data was successfully saved to %1.</source>
- <translation type="unfinished">La información de la cartera fué guardada exitosamente a %1</translation>
- </message>
- </context>
-</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_es_VE.ts b/src/qt/locale/bitcoin_es_VE.ts
index bf9e557a9f..8cb4efe6bf 100644
--- a/src/qt/locale/bitcoin_es_VE.ts
+++ b/src/qt/locale/bitcoin_es_VE.ts
@@ -70,6 +70,12 @@
<translation type="unfinished">Estas son sus direcciones Bitcoin para enviar pagos. Compruebe siempre la cantidad y la dirección de recibo antes de transferir monedas.</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Lista de tus direcciones de Bitcoin para recibir pagos. Para la creacion de una nueva direccion seleccione en la pestana "recibir" la opcion "Crear nueva direccion"
+Registrarse solo es posible utilizando una direccion tipo "Legal"</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">Copiar dirección</translation>
</message>
@@ -749,6 +755,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -915,10 +942,12 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirme el restablecimiento de las opciones</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Reinicio del cliente para activar cambios.</translation>
</message>
<message>
@@ -1294,10 +1323,6 @@
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduce una etiqueta para esta dirección para añadirla a la lista de direcciones utilizadas</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Paga a:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts
index beba4e31f9..d9c6eed537 100644
--- a/src/qt/locale/bitcoin_et.ts
+++ b/src/qt/locale/bitcoin_et.ts
@@ -528,6 +528,10 @@
<translation type="unfinished">Ajakohane</translation>
</message>
<message>
+ <source>Open Wallet</source>
+ <translation type="unfinished">Ava Rahakott</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Aken</translation>
</message>
@@ -702,6 +706,14 @@
</message>
</context>
<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>Open Wallet</source>
+ <extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
+ <translation type="unfinished">Ava Rahakott</translation>
+ </message>
+ </context>
+<context>
<name>CreateWalletDialog</name>
<message>
<source>Wallet</source>
@@ -757,6 +769,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -906,6 +939,7 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Kinnita valikute algseadistamine</translation>
</message>
<message>
@@ -1370,10 +1404,6 @@
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
<translation type="unfinished">Summa koos tehingu tasuga %1 ületab sinu jääki.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Maksepäring aegunud.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -1420,10 +1450,6 @@
<source>Message:</source>
<translation type="unfinished">Sõnum:</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Maksa :</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1552,10 +1578,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/kinnitamata</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 kinnitust</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_eu.ts b/src/qt/locale/bitcoin_eu.ts
index b9bd7cd38a..c215936b0e 100644
--- a/src/qt/locale/bitcoin_eu.ts
+++ b/src/qt/locale/bitcoin_eu.ts
@@ -70,6 +70,12 @@
<translation type="unfinished">Hauek dira zuk dirua jaso dezaketen Bitcoin helbideak. Egiaztatu beti diru-kopurua eta dirua jasoko duen helbidea zuzen egon daitezen, txanponak bidali baino lehen.</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Hauek dira ordainketak jasotzeko zure Bitcoin helbideak. Jaso taulako 'Jasotzeko helbide berri bat sortu' botoia erabili helbide berri bat sortzeko.
+Sinatzea 'legacy' motako helbideekin soilik da posible</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">&amp;Helbidea kopiatu</translation>
</message>
@@ -86,6 +92,11 @@
<translation type="unfinished">Helbide lista esportatu</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Komaz bereizitako fitxategia</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">Akats bat egon da helbide lista %1-ean gordetzen sahiatzean. Mesedez, saiatu berriro.</translation>
@@ -233,6 +244,17 @@
</message>
</context>
<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">Ranaway exception</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">Barne errorea</translation>
+ </message>
+ </context>
+<context>
<name>QObject</name>
<message>
<source>Error: %1</source>
@@ -246,6 +268,18 @@
<source>Amount</source>
<translation type="unfinished">Kopurua</translation>
</message>
+ <message>
+ <source>Internal</source>
+ <translation type="unfinished">Barnekoa</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation type="unfinished">%1 e</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation type="unfinished">%1 o</translation>
+ </message>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
@@ -295,6 +329,70 @@
<source>Done loading</source>
<translation type="unfinished">Zamaketa amaitua</translation>
</message>
+ <message>
+ <source>Importing…</source>
+ <translation type="unfinished">Inportatzen...</translation>
+ </message>
+ <message>
+ <source>Loading wallet…</source>
+ <translation type="unfinished">Diruzorroa kargatzen...</translation>
+ </message>
+ <message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Zenbatekoa falta da</translation>
+ </message>
+ <message>
+ <source>No addresses available</source>
+ <translation type="unfinished">Ez dago helbiderik eskuragarri</translation>
+ </message>
+ <message>
+ <source>Replaying blocks…</source>
+ <translation type="unfinished">Blokeak errepikatzen...</translation>
+ </message>
+ <message>
+ <source>Rescanning…</source>
+ <translation type="unfinished">Bereskaneatzen...</translation>
+ </message>
+ <message>
+ <source>Starting network threads…</source>
+ <translation type="unfinished">Sareko hariak abiarazten...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation type="unfinished">Iturri kodea %s-tik dago eskuragarri.</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation type="unfinished">Transakzio kantitatea txikiegia da kuota ordaintzeko.</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation type="unfinished">Hau software esperimentala da</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation type="unfinished">transakzio kopurua txikiegia</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation type="unfinished">Transakzio luzeegia</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation type="unfinished">hasierako giltzak sortzeko ezgai</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation type="unfinished">Giltzak sortzeko ezgai</translation>
+ </message>
+ <message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">Blokeak egiaztatzen...</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)…</source>
+ <translation type="unfinished">Diruzorroak egiaztatzen...</translation>
+ </message>
</context>
<context>
<name>BitcoinGUI</name>
@@ -347,6 +445,10 @@
<translation type="unfinished">Diruzorro berri bat sortu</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Minimizatu</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Diruzorroa:</translation>
</message>
@@ -380,18 +482,62 @@
<translation type="unfinished">&amp;Jaso</translation>
</message>
<message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;Aukerak...</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;Diruzorroa enkriptatu...</translation>
+ </message>
+ <message>
<source>Encrypt the private keys that belong to your wallet</source>
<translation type="unfinished">Zure diru-zorroari dagozkion giltza pribatuak enkriptatu.</translation>
</message>
<message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">Diruzorroaren &amp;segurtasun kopia egin...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;aldatu pasahitza</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">sinatu &amp;mezua</translation>
+ </message>
+ <message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
<translation type="unfinished">Sinatu mezuak Bitcoinen helbideekin, jabetza frogatzeko.</translation>
</message>
<message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">Mezua &amp;balioztatu</translation>
+ </message>
+ <message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
<translation type="unfinished">Egiaztatu mesua Bitcoin helbide espezifikoarekin erregistratu direla ziurtatzeko</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">&amp;kargatu PSBT fitxategitik...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">Ireki&amp;URI...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">Diruzorroa itxi...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">Diruzorroa sortu...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">Diru-zorro guztiak itxi...</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation type="unfinished">&amp;Artxiboa</translation>
</message>
@@ -408,6 +554,26 @@
<translation type="unfinished">Fitxen tresna-barra</translation>
</message>
<message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Sarearekin sinkronizatzen...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Diskoko blokeak indexatzen...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Diskoko blokeak prozesatzen...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Diskoko blokeak berzerrendatzen</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">Pareekin konektatzen...</translation>
+ </message>
+ <message>
<source>Show the list of used sending addresses and labels</source>
<translation type="unfinished"> Bidalketa-helbideen eta etiketen zerrenda erakutsi</translation>
</message>
@@ -431,6 +597,10 @@
<translation type="unfinished">%1 atzetik</translation>
</message>
<message>
+ <source>Catching up…</source>
+ <translation type="unfinished">Harrapatzen...</translation>
+ </message>
+ <message>
<source>Last received block was generated %1 ago.</source>
<translation type="unfinished">Jasotako azken blokea duela %1 sortu zen.</translation>
</message>
@@ -459,6 +629,10 @@
<translation type="unfinished">Partzialki sinatutako Bitcoin transakzioa kargatu</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">kargatu PSBT arbeletik...</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Partzialki sinatutako Bitcoin transakzioa kargatu arbeletik</translation>
</message>
@@ -503,6 +677,11 @@
<translation type="unfinished">Ez dago diru-zorrorik eskura</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Diruzorroaren izena</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Lehioa</translation>
</message>
@@ -518,6 +697,14 @@
<source>%1 client</source>
<translation type="unfinished">%1 bezeroa</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Ezkutatu</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">E&amp;rakutsi</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -527,6 +714,11 @@
</translation>
</message>
<message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">Erakutxi kideen fitxa</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Akatsa: %1</translation>
</message>
@@ -674,10 +866,22 @@
<translation type="unfinished">zenbatekoaren kopia</translation>
</message>
<message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiatu &amp;Etiketa</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Kopia kopurua</translation>
</message>
<message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Kopiatu kuota</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Kopia kuotaren ondoren</translation>
+ </message>
+ <message>
<source>Copy bytes</source>
<translation type="unfinished">Kopiatu byte-ak</translation>
</message>
@@ -718,6 +922,11 @@
<translation type="unfinished">Diruzorroa sortu</translation>
</message>
<message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">Diru-zorroa sortzen&lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
<source>Create wallet failed</source>
<translation type="unfinished">Diruzorroa sortzen hutsegitea</translation>
</message>
@@ -725,8 +934,25 @@
<source>Create wallet warning</source>
<translation type="unfinished">Diru-zorroa sortzearen buruzko oharra</translation>
</message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Ezin dira sinatzaileak zerrendatu</translation>
+ </message>
</context>
<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">Kargatu diruzorroak</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">Diruzorroak kargatzen...</translation>
+ </message>
+</context>
+<context>
<name>OpenWalletActivity</name>
<message>
<source>Open wallet failed</source>
@@ -745,7 +971,12 @@
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">Diruzorroa zabaldu</translation>
</message>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">&lt;b&gt;%1&lt;/b&gt; diruzorroa irekitzen ...</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
@@ -756,7 +987,11 @@
<source>Close all wallets</source>
<translation type="unfinished">Diruzorro guztiak itxi</translation>
</message>
- </context>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation type="unfinished">Ziur diruzorro guztiak itxi nahi dituzula?</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
<message>
@@ -784,10 +1019,18 @@
<translation type="unfinished">Desgaitu gako pribatuak</translation>
</message>
<message>
+ <source>Make Blank Wallet</source>
+ <translation type="unfinished">Egin diruzorro hutsa...</translation>
+ </message>
+ <message>
<source>Descriptor Wallet</source>
<translation type="unfinished">Deskriptorearen zorroa</translation>
</message>
<message>
+ <source>External signer</source>
+ <translation type="unfinished">Kanpo sinatzailea</translation>
+ </message>
+ <message>
<source>Create</source>
<translation type="unfinished">Sortu</translation>
</message>
@@ -830,13 +1073,46 @@
<context>
<name>FreespaceChecker</name>
<message>
+ <source>A new data directory will be created.</source>
+ <translation type="unfinished">Datu direktorio berria sortuko da.</translation>
+ </message>
+ <message>
<source>name</source>
<translation type="unfinished">izena</translation>
</message>
- </context>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation type="unfinished">Bidea existitzen da, eta ez da direktorioa.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation type="unfinished">Ezin da datu direktoria hemen sortu.</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -856,7 +1132,19 @@
<source>Welcome to %1.</source>
<translation type="unfinished">Ongietorri %1-ra</translation>
</message>
- </context>
+ <message>
+ <source> GB</source>
+ <translation type="unfinished">GB</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation type="unfinished">Erabili datu direktorio lehenetsia</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation type="unfinished">Erabili datu direktorio pertsonalizatu bat:</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
<message>
@@ -873,6 +1161,13 @@
</message>
</context>
<context>
+ <name>ShutdownWindow</name>
+ <message>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1Itzaltzen ari da...</translation>
+ </message>
+ </context>
+<context>
<name>ModalOverlay</name>
<message>
<source>Form</source>
@@ -883,6 +1178,14 @@
<translation type="unfinished">Gainerako blokeen kopurua.</translation>
</message>
<message>
+ <source>Unknown…</source>
+ <translation type="unfinished">Ezezaguna...</translation>
+ </message>
+ <message>
+ <source>calculating…</source>
+ <translation type="unfinished">kalkulatzen...</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation type="unfinished">Azken blokearen unea</translation>
</message>
@@ -891,6 +1194,10 @@
<translation type="unfinished">Aurrerapena</translation>
</message>
<message>
+ <source>Progress increase per hour</source>
+ <translation type="unfinished">Aurrerapenaren igoera orduko</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation type="unfinished">Izkutatu</translation>
</message>
@@ -1011,10 +1318,12 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Berretsi aukeren berrezarpena</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Bezeroa berrabiarazi behar da aldaketak aktibatzeko.</translation>
</message>
<message>
@@ -1054,21 +1363,69 @@
<translation type="unfinished">Ez dago eskuragarri:</translation>
</message>
<message>
+ <source>Balances</source>
+ <translation type="unfinished">Saldoa</translation>
+ </message>
+ <message>
<source>Total:</source>
<translation type="unfinished">Guztira:</translation>
</message>
+ <message>
+ <source>Your current total balance</source>
+ <translation type="unfinished">Zure oraingo erabateko saldoa</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation type="unfinished">Gastagarria:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation type="unfinished">Transakzio berriak</translation>
+ </message>
</context>
<context>
<name>PSBTOperationsDialog</name>
<message>
+ <source>Dialog</source>
+ <translation type="unfinished">Elkarrizketa</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation type="unfinished">Sinatu Tx</translation>
+ </message>
+ <message>
<source>Copy to Clipboard</source>
<translation type="unfinished">Kopiatu arbelera</translation>
</message>
<message>
+ <source>Save…</source>
+ <translation type="unfinished">Gorde...</translation>
+ </message>
+ <message>
<source>Close</source>
<translation type="unfinished">Itxi</translation>
</message>
- </context>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation type="unfinished">Gorde transakzioko data</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation type="unfinished">PSBT diskoan gorde da.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation type="unfinished">Kopuru osoa</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation type="unfinished">edo</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation type="unfinished">Transakzioaren egoera ezezaguna da.</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
<message>
@@ -1084,6 +1441,21 @@
<translation type="unfinished">Erabiltzaile agentea</translation>
</message>
<message>
+ <source>Peer</source>
+ <extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
+ <translation type="unfinished">Kidea</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
+ <translation type="unfinished">Bidalia</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <extracomment>Title of Peers Table column which indicates the total amount of network information we have received from the peer.</extracomment>
+ <translation type="unfinished">Jasoa</translation>
+ </message>
+ <message>
<source>Address</source>
<extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
<translation type="unfinished">Helbidea</translation>
@@ -1093,10 +1465,103 @@
<extracomment>Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</extracomment>
<translation type="unfinished">Mota</translation>
</message>
+ <message>
+ <source>Network</source>
+ <extracomment>Title of Peers Table column which states the network the peer connected through.</extracomment>
+ <translation type="unfinished">Sarea</translation>
+ </message>
</context>
<context>
+ <name>QRImageWidget</name>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">&amp;Gorde irudia...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation type="unfinished">&amp;kopiatu irudia</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation type="unfinished">Gorde QR kodea</translation>
+ </message>
+ <message>
+ <source>PNG Image</source>
+ <extracomment>Expanded name of the PNG file format. See: https://en.wikipedia.org/wiki/Portable_Network_Graphics.</extracomment>
+ <translation type="unfinished">PNG irudia</translation>
+ </message>
+</context>
+<context>
<name>RPCConsole</name>
<message>
+ <source>Client version</source>
+ <translation type="unfinished">Bezeroaren bertsioa</translation>
+ </message>
+ <message>
+ <source>&amp;Information</source>
+ <translation type="unfinished">&amp;Informazioa</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation type="unfinished">Orokorra</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation type="unfinished">Datu direktorioa</translation>
+ </message>
+ <message>
+ <source>Blocksdir</source>
+ <translation type="unfinished">Blokeen direktorioa</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation type="unfinished">Abiatzeko ordua</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation type="unfinished">Sarea</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation type="unfinished">Izena</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation type="unfinished">Konexio kopurua</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation type="unfinished">Diruzorroa:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation type="unfinished">(bat ere ez)</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation type="unfinished">&amp;Berrezarri</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation type="unfinished">Jasoa</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation type="unfinished">Bidalia</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation type="unfinished">&amp;Kideak</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation type="unfinished">Debekatutako kideak</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation type="unfinished">Bertsioa</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Erabiltzaile agentea</translation>
</message>
@@ -1105,10 +1570,39 @@
<translation type="unfinished">Adabegiaren leihoa</translation>
</message>
<message>
+ <source>Permissions</source>
+ <translation type="unfinished">Baimenak</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation type="unfinished">Zerbitzuak</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation type="unfinished">Azken blokearen unea</translation>
</message>
<message>
+ <source>Clear console</source>
+ <translation type="unfinished">Garbitu kontsola</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation type="unfinished">&amp;Deskonektatu</translation>
+ </message>
+ <message>
+ <source>Executing…</source>
+ <extracomment>A console message indicating an entered command is currently being executed.</extracomment>
+ <translation type="unfinished">Exekutatzen...</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation type="unfinished">Bai</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation type="unfinished">Ez</translation>
+ </message>
+ <message>
<source>To</source>
<translation type="unfinished">Ra</translation>
</message>
@@ -1116,7 +1610,15 @@
<source>From</source>
<translation type="unfinished">Tik</translation>
</message>
- </context>
+ <message>
+ <source>Never</source>
+ <translation type="unfinished">Inoiz ez</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation type="unfinished">Ezezaguna</translation>
+ </message>
+</context>
<context>
<name>ReceiveCoinsDialog</name>
<message>
@@ -1132,6 +1634,30 @@
<translation type="unfinished">&amp;Mezua:</translation>
</message>
<message>
+ <source>Clear all fields of the form.</source>
+ <translation type="unfinished">Garbitu formularioko eremu guztiak.</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation type="unfinished">Garbitu</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation type="unfinished">Erakutsi</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation type="unfinished">Ezabatu</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation type="unfinished">Kopiatu &amp;URI</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiatu &amp;Etiketa</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">Ezin da diruzorroa desblokeatu.</translation>
</message>
@@ -1139,10 +1665,18 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>Address:</source>
+ <translation type="unfinished">Helbidea:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation type="unfinished">Kopurua:</translation>
</message>
<message>
+ <source>Label:</source>
+ <translation type="unfinished">Etiketa:</translation>
+ </message>
+ <message>
<source>Message:</source>
<translation type="unfinished">Mezua:</translation>
</message>
@@ -1151,9 +1685,25 @@
<translation type="unfinished">Diruzorroa:</translation>
</message>
<message>
+ <source>Copy &amp;URI</source>
+ <translation type="unfinished">Kopiatu &amp;URI</translation>
+ </message>
+ <message>
<source>Copy &amp;Address</source>
<translation type="unfinished">&amp;Helbidea kopiatu</translation>
</message>
+ <message>
+ <source>&amp;Verify</source>
+ <translation type="unfinished">&amp;Egiaztatu</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">&amp;Gorde irudia...</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation type="unfinished">Ordainketaren informazioa</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1173,7 +1723,15 @@
<source>(no label)</source>
<translation type="unfinished">(izendapenik ez)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation type="unfinished">(mezurik ez)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation type="unfinished">Eskatua</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -1181,6 +1739,10 @@
<translation type="unfinished">Txanponak bidali</translation>
</message>
<message>
+ <source>automatically selected</source>
+ <translation type="unfinished">automatikoki aukeratua</translation>
+ </message>
+ <message>
<source>Quantity:</source>
<translation type="unfinished">Zenbat:</translation>
</message>
@@ -1205,18 +1767,42 @@
<translation type="unfinished">Bueltak:</translation>
</message>
<message>
+ <source>Transaction Fee:</source>
+ <translation type="unfinished">Transakzio kuota:</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation type="unfinished">Kilobyteko</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation type="unfinished">Izkutatu</translation>
</message>
<message>
+ <source>Recommended:</source>
+ <translation type="unfinished">Gomendatutakoa:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation type="unfinished">Neurrira:</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation type="unfinished">Hainbat jasotzaileri batera bidali</translation>
</message>
<message>
+ <source>Clear all fields of the form.</source>
+ <translation type="unfinished">Garbitu formularioko eremu guztiak.</translation>
+ </message>
+ <message>
<source>Dust:</source>
<translation type="unfinished">Hautsa:</translation>
</message>
<message>
+ <source>Choose…</source>
+ <translation type="unfinished">Aukeratu...</translation>
+ </message>
+ <message>
<source>Balance:</source>
<translation type="unfinished">Saldoa:</translation>
</message>
@@ -1225,6 +1811,10 @@
<translation type="unfinished">Bidalketa berretsi</translation>
</message>
<message>
+ <source>S&amp;end</source>
+ <translation type="unfinished">Bidali</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Kopia kopurua</translation>
</message>
@@ -1233,6 +1823,14 @@
<translation type="unfinished">zenbatekoaren kopia</translation>
</message>
<message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Kopiatu kuota</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Kopia kuotaren ondoren</translation>
+ </message>
+ <message>
<source>Copy bytes</source>
<translation type="unfinished">Kopiatu byte-ak</translation>
</message>
@@ -1245,6 +1843,49 @@
<translation type="unfinished">Kopiatu aldaketa</translation>
</message>
<message>
+ <source>Sign on device</source>
+ <extracomment>"device" usually means a hardware wallet.</extracomment>
+ <translation type="unfinished">Sinatu gailuan</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">Konektatu zure hardware diruzorroa lehenago.</translation>
+ </message>
+ <message>
+ <source>Sign failed</source>
+ <translation type="unfinished">Sinadurak hutsegitea</translation>
+ </message>
+ <message>
+ <source>External signer not found</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Kanpo sinatzailea ez da aurkitu</translation>
+ </message>
+ <message>
+ <source>External signer failure</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Kanpo sinatzailearen hutsegitea</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation type="unfinished">Gorde transakzioko data</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation type="unfinished">PSBT gordeta</translation>
+ </message>
+ <message>
+ <source>External balance:</source>
+ <translation type="unfinished">Kanpo saldoa:</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation type="unfinished">edo</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation type="unfinished">Kopuru osoa</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation type="unfinished">Txanponen bidalketa berretsi</translation>
</message>
@@ -1279,6 +1920,10 @@
<translation type="unfinished">&amp;Etiketa:</translation>
</message>
<message>
+ <source>Choose previously used address</source>
+ <translation type="unfinished">Aukeratu lehenago aukeraturiko helbidea</translation>
+ </message>
+ <message>
<source>Paste address from clipboard</source>
<translation type="unfinished">Arbeletik helbidea itsatsi</translation>
</message>
@@ -1286,18 +1931,38 @@
<source>Message:</source>
<translation type="unfinished">Mezua:</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Honi ordaindu:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Choose previously used address</source>
+ <translation type="unfinished">Aukeratu lehenago aukeraturiko helbidea</translation>
+ </message>
+ <message>
<source>Paste address from clipboard</source>
<translation type="unfinished">Arbeletik helbidea itsatsi</translation>
</message>
<message>
+ <source>Enter the message you want to sign here</source>
+ <translation type="unfinished">Sartu sinatu nahi duzun mezua hemen</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation type="unfinished">Sinadura</translation>
+ </message>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation type="unfinished">Kopiatu oraingo sinadura sistemaren arbelera</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation type="unfinished">Sinatu &amp;Mezua</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation type="unfinished">&amp;Egiaztatu mezua</translation>
+ </message>
+ <message>
<source>No error</source>
<translation type="unfinished">Ez dago errorerik</translation>
</message>
@@ -1313,19 +1978,30 @@
<source>Please check the signature and try again.</source>
<translation type="unfinished">Mesedez, begiratu sinadura eta saiatu berriro.</translation>
</message>
- </context>
+ <message>
+ <source>Message verification failed.</source>
+ <translation type="unfinished">Mezuen egiaztatzeak huts egin du</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation type="unfinished">Mezua egiaztatua.</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abandonatuta</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/konfirmatu gabe</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 konfirmazio</translation>
</message>
<message>
@@ -1407,7 +2083,15 @@
<source>Amount</source>
<translation type="unfinished">Kopurua</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation type="unfinished">egia</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation type="unfinished">faltsua</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
@@ -1430,6 +2114,10 @@
<translation type="unfinished">Izendapen</translation>
</message>
<message>
+ <source>Unconfirmed</source>
+ <translation type="unfinished">Baieztatu gabea</translation>
+ </message>
+ <message>
<source>Confirmed (%1 confirmations)</source>
<translation type="unfinished">Konfirmatuta (%1 konfirmazio)</translation>
</message>
@@ -1529,6 +2217,15 @@
<translation type="unfinished">Kopuru minimoa</translation>
</message>
<message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiatu &amp;Etiketa</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Komaz bereizitako fitxategia</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">Berretsia</translation>
</message>
@@ -1571,6 +2268,18 @@
<translation type="unfinished">Txanponak bidali</translation>
</message>
<message>
+ <source>Current fee:</source>
+ <translation type="unfinished">Oraingo kuota:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation type="unfinished">Kuota berria:</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation type="unfinished">PSBT kopiatua</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">Diruzorro lehenetsia</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts
index 77f73f70d8..5c4fba8ac1 100644
--- a/src/qt/locale/bitcoin_fa.ts
+++ b/src/qt/locale/bitcoin_fa.ts
@@ -3,15 +3,15 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">برای ویرایش نشانی یا برچسب زدن کلیک ‌راست کنید</translation>
+ <translation type="unfinished">برای ویرایش نشانی یا برچسب راست-کلیک کنید</translation>
</message>
<message>
<source>Create a new address</source>
- <translation type="unfinished">آدرس جدید ایجاد کنید</translation>
+ <translation type="unfinished">یک آدرس جدید ایجاد کنید</translation>
</message>
<message>
<source>&amp;New</source>
- <translation type="unfinished">و جدید</translation>
+ <translation type="unfinished">&amp;جدید</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
@@ -27,7 +27,7 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished">حذ٠آدرس ‌انتخاب شده از Ùهرست</translation>
+ <translation type="unfinished">حذ٠آدرس ‌انتخاب شده ÛŒ جاری از Ùهرست</translation>
</message>
<message>
<source>Enter address or label to search</source>
@@ -39,13 +39,21 @@
</message>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">صدور</translation>
+ <translation type="unfinished">&amp;صدور</translation>
</message>
<message>
<source>&amp;Delete</source>
<translation type="unfinished">حذÙ</translation>
</message>
<message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">آدرس را برای ارسال کوین وارد کنید</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">آدرس را برای دریاÙت کوین وارد کنید</translation>
+ </message>
+ <message>
<source>C&amp;hoose</source>
<translation type="unfinished">انتخاب</translation>
</message>
@@ -160,7 +168,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished">هشدار: اگر کی٠پول خود را رمزگذاری کنید Ùˆ عبارت خود را گام کنید ØŒ این کار را انجام Ù…ÛŒ دهید &lt;b&gt;تمام کویت های خود را از دست &lt;/b&gt;استÙاده کنید!
+ <translation type="unfinished">هشدار: اگر کی٠پول خود را رمزگذاری کنید و عبارت خود را گم کنید ، &lt;b&gt;تمام کویت های خود را از دست &lt;/b&gt;خواهید داد!
</translation>
</message>
<message>
@@ -251,12 +259,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
- <source>Runaway exception</source>
- <translation type="unfinished">استثناء Ùراری (این استثناء نشان دهنده این است Ú©Ù‡ هسته بیتکوین نتوانست چیزی را در Ú©ÛŒÙ(والت) بنویسد.)</translation>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Ùایل تنظیمات %1 ممکن است خراب یا نامعتبر باشد.</translation>
</message>
<message>
- <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <translation type="unfinished"> خطای تخریب کننده ای روی داده است.%1 نمیتواند بصورت ایمن ادامه پیدا کند و پایان می یابد.</translation>
+ <source>Runaway exception</source>
+ <translation type="unfinished">استثناء Ùراری (این استثناء نشان دهنده این است Ú©Ù‡ هسته بیتکوین نتوانست چیزی را در Ú©ÛŒÙ(والت) بنویسد.)</translation>
</message>
<message>
<source>Internal error</source>
@@ -591,10 +599,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">خطا در خواندن رکورد بعدی از پایگاه داده کی٠پول</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">خطا در بارگذاری پایگاه داده ها</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">خطا: مکان نما در پایگاه داده ایجاد نشد</translation>
</message>
@@ -692,10 +696,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">توصیÙگرهای Ùایل به اندازه کاÙÛŒ در دسترس نیست</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">حالت Prune با -coinstatsindex ناسازگار است.</translation>
- </message>
- <message>
<source>Pruning blockstore…</source>
<translation type="unfinished">هرس بلوک Ùروشی…</translation>
</message>
@@ -773,6 +773,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">حجم تراکنش خیلی زیاد است</translation>
</message>
<message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">قادر به پیدا کردن UTXO برای ورودی جانبی نیست.</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation type="unfinished">نمیتوان کلید های اولیه را تولید کرد.</translation>
</message>
@@ -802,10 +806,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">قوانین جدید ناشناخته Ùعال شد (‌%iversionbit)</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">ارتقا دادن پایگاه داده UTXO</translation>
- </message>
- <message>
<source>Verifying blocks…</source>
<translation type="unfinished">در حال تأیید بلوک‌ها…</translation>
</message>
@@ -934,6 +934,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">پیام تایید</translation>
</message>
<message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">پیام ها را تأیید کنید تا مطمئن شوید با آدرس های مشخص شده بیت کوین امضا شده اند
+ </translation>
+ </message>
+ <message>
<source>&amp;Load PSBT from file…</source>
<translation type="unfinished">بارگیری PSBT از پرونده</translation>
</message>
@@ -1012,7 +1017,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>سابقه تراکنش بلوک(های) %n پردازش شد.</numerusform>
</translation>
</message>
<message>
@@ -1086,6 +1091,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">کی٠پول را ببندید</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">بازیابی کی٠پول…</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">بازیابی یک کی٠پول از یک Ùایل پشتیبان</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">همه‌ی کی٠پول‌ها را ببند</translation>
</message>
@@ -1099,6 +1114,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">هیچ کی٠پولی در دسترس نمی باشد</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">داده های کی٠پول</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">بارگیری پشتیبان‌گیری کی٠پول</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">بازیابی کی٠پول</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">نام کی٠پول</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">پنجره</translation>
</message>
@@ -1114,11 +1149,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">کلاینت: %1</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">مخÙÛŒ Ú©Ù†</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n اتصال(های) Ùعال به شبکه بیت کوین.</numerusform>
</translation>
</message>
<message>
@@ -1142,6 +1181,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ùعال‌سازی Ùعالیت شبکه</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">پیش‌همگام‌سازی سرصÙحه‌ها (%1%)…</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">خطا: %1</translation>
</message>
@@ -1399,6 +1442,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">نمی‌توان امضاکنندگان را Ùهرست کرد</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">تعداد زیادی امضاکننده خارجی پیدا شد</translation>
+ </message>
</context>
<context>
<name>LoadWalletsActivity</name>
@@ -1441,6 +1488,34 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">بازیابی کی٠پول</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">بازیابی کی٠پول &lt;b&gt;%1&lt;/b&gt; ...</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">بازیابی کی٠پول انجام نشد</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">هشدار بازیابی کی٠پول</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">بازیابی پیام کی٠پول</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1472,7 +1547,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
- <translation type="unfinished">کی٠پول را رمز نگاری نمائید. کی٠پول با کلمات رمز انتخاب خودتان رمز نگاری خواهد شد</translation>
+ <translation type="unfinished">کی٠پول را رمز نگاری نمائید. کی٠پول با کلمات رمز دلخواه شما رمز نگاری خواهد شد</translation>
</message>
<message>
<source>Encrypt Wallet</source>
@@ -1593,13 +1668,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Bitcoin</source>
<translation type="unfinished">بیت کوین</translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(%1 گیگابایت لازم است)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n گیگابایت Ùضای موجود</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 برای زنجیر کامل نیاز است)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(از %n گیگابایت مورد نیاز)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n گیگابایت برای زنجیره کامل مورد نیاز است)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1613,7 +1698,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>(برای بازیابی نسخه‌های پشتیبان %n روز (های) قدیمی کاÙÛŒ است)</numerusform>
</translation>
</message>
<message>
@@ -1649,6 +1734,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">گیگابایت</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">وقتی تأیید را کلیک می‌کنید، %1 شروع به دانلود و پردازش زنجیره بلاک %4 کامل (%2 گیگابایت) می‌کند که با اولین تراکنش‌ها در %3 شروع می‌شود که %4 در ابتدا راه‌اندازی می شود.</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished">اگر تصمیم بگیرید Ú©Ù‡ Ùضای ذخیره سازی زنجیره بلوک (هرس) را محدود کنید ØŒ داده های تاریخی باید بارگیری Ùˆ پردازش شود ØŒ اما اگر آن را حذ٠کنید ØŒ اگر شما دیسک Ú©Ù… استÙاده کنید.
 </translation>
@@ -1740,6 +1829,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">ناشناخته. هماهنگ‌سازی سربرگ‌ها (%1، %2%) </translation>
</message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">ناشناس. پیش‌همگام‌سازی سرصÙحه‌ها (%1ØŒ %2% )…</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1776,6 +1869,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">اندازه کش پایگاه داده.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">گزینه های تنظیم شده در این Ú¯Ùتگو توسط خط Ùرمان لغو Ù…ÛŒ شوند:</translation>
+ </message>
+ <message>
<source>Open Configuration File</source>
<translation type="unfinished">بازکردن Ùایل پیکربندی</translation>
</message>
@@ -2004,15 +2101,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">باز نشانی گزینه ها را تأیید کنید
  </translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">کلاینت نیازمند ریست شدن است برای Ùعال کردن تغییرات</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">تنظیمات Ùعلی در "%1" پشتیبان گیری خواهد شد.</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">کلاینت خاموش خواهد شد.آیا میخواهید ادامه دهید؟</translation>
</message>
<message>
@@ -2053,6 +2158,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">نمی توان تنظیم "%1"، %2 را خواند.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2168,6 +2280,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">یا</translation>
</message>
<message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation type="unfinished">%1Transaction has unsigned inputs.</translation>
+ </message>
+ <message>
<source>Transaction still needs signature(s).</source>
<translation type="unfinished">عملیات هنوز به امضا(ها) نیاز دارد.</translation>
</message>
@@ -2229,6 +2345,11 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">همتا </translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">سن</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">مسیر</translation>
@@ -2405,29 +2526,22 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished"> ما آدرس‌ها را به این همتا ارسال می‌کنیم.</translation>
</message>
<message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">رله آدرس</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">تعداد کل آدرس‌های پردازش شده، به استثنای آدرس‌هایی که به دلیل محدودیت نرخ حذ٠شده‌اند.</translation>
- </message>
- <message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">آدرس ها پردازش شد</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">تعداد Ú©Ù„ آدرس‌ها به دلیل محدودیت نرخ کاهش یاÙت.</translation>
- </message>
- <message>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">آدرس ها با نرخ محدود</translation>
</message>
<message>
@@ -3028,7 +3142,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Copy amount</source>
- <translation type="unfinished">مقدار کپی</translation>
+ <translation type="unfinished">کپی مقدار</translation>
</message>
<message>
<source>Copy fee</source>
@@ -3167,10 +3281,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">کارمزد بیشتر از %1 است,این یعنی کارمزد خیلی زیادی در نظر گرÙته شده است.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">درخواست پرداخت منقضی شد یا تاریخ آن گذشت.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3238,25 +3348,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>Message:</source>
<translation type="unfinished">پیام:</translation>
</message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">این یک درخواست پرداخت غیرمجاز است.
- </translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">این یک درخواست پرداخت معتبر است.
- </translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">پرداخت کردن</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">یادداشت:</translation>
- </message>
-</context>
+ </context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -3421,14 +3513,17 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<name>TransactionDesc</name>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">رها شده</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/تأیید نشده</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 تأییدیه</translation>
</message>
<message>
@@ -3859,11 +3954,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">صدور</translation>
+ <translation type="unfinished">&amp;صدور</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation type="unfinished">داده های موجود در برگه Ùعلی را به یک Ùایل صادر کنید</translation>
+ <translation type="unfinished">خروجی گرÙتن داده‌ها از برگه ÛŒ کنونی در یک پوشه</translation>
</message>
<message>
<source>Backup Wallet</source>
diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts
index c1321b0bd4..46e9bebeb0 100644
--- a/src/qt/locale/bitcoin_fi.ts
+++ b/src/qt/locale/bitcoin_fi.ts
@@ -246,6 +246,10 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Asetustiedosto %1 saattaa olla vioittunut tai virheellinen.</translation>
+ </message>
+ <message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
<translation type="unfinished">Peruuttamaton virhe on tapahtunut. %1 ei voi enää jatkaa turvallisesti ja sammutetaan.</translation>
</message>
@@ -419,10 +423,6 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">Virhe: Dump-tiedoston versio ei ole tuettu. Tämä bitcoin-lompakon versio tukee vain version 1 dump-tiedostoja. Annetun dump-tiedoston versio %s</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Virhe: Saapuvien yhteyksien kuuntelu epäonnistui (kuuntelu palautti virheen %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Siirtomaksun arviointi epäonnistui. Odota muutama lohko tai käytä -fallbackfee -valintaa..</translation>
</message>
@@ -603,10 +603,6 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">Virhe seuraavan tietueen lukemisessa lompakon tietokannasta</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Virhe päivittäessä chainstate-tietokantaa</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Virhe: Tietokantaan ei voitu luoda kursoria.</translation>
</message>
@@ -715,8 +711,8 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">Pitää määritellä portti argumentilla -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Välityspalvelinta ei ole määritetty. Käytä -proxy=&lt;ip&gt; tai -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Osoitteita ei ole saatavilla</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -727,10 +723,6 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">Karsintaa ei voi toteuttaa negatiivisella arvolla.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Karsintatila ei ole yhteenopiva -coinstatsindex:n kanssa.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Karsittu tila ei ole yhteensopiva -txindex:n kanssa.</translation>
</message>
@@ -887,10 +879,6 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">Lokikategoriaa %s=%s ei tueta.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Päivitetään UTXO-tietokantaa</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">User Agent -kommentti (%s) sisältää turvattomia merkkejä.</translation>
</message>
@@ -1105,8 +1093,8 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Käsitelty %n lohko rahansiirtohistoriasta.</numerusform>
+ <numerusform>Käsitelty %n lohkoa rahansiirtohistoriasta.</numerusform>
</translation>
</message>
<message>
@@ -1206,6 +1194,16 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">Lompakoita ei ole saatavilla</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Lompakkotiedot</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Lompakon nimi</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Ikkuna</translation>
</message>
@@ -1221,6 +1219,10 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<source>%1 client</source>
<translation type="unfinished">%1-asiakas</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Piilota</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1500,7 +1502,7 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<source>Can't list signers</source>
<translation type="unfinished">Allekirjoittajia ei voida listata</translation>
</message>
-</context>
+ </context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1706,13 +1708,26 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(%1 GB tarvitaan)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB tarvitaan koko ketjuun)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1759,10 +1774,6 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">Tämä on ensimmäinen kerta, kun %1 on käynnistetty, joten voit valita data-hakemiston paikan.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Kun valitset OK, %1 aloittaa lataamaan ja käsittelemään koko %4 lohkoketjua (%2GB) aloittaen ensimmäisestä siirrosta %3 jolloin %4 käynnistettiin ensimmäistä kertaa.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Rajoita lohkoketjun tallennus</translation>
</message>
@@ -1875,7 +1886,7 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Tuntematon. Synkronoidaan järjestysnumeroita (%1,%2%)...</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2116,10 +2127,6 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">lähin vastaavuus "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Seuraavat komentorivillä tai asetustiedostossa annetut määritykset menevät tässä ikkunassa asetettujen asetusten edelle:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Peruuta</translation>
</message>
@@ -2138,14 +2145,17 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Varmista asetusten palautus</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Ohjelman uudelleenkäynnistys aktivoi muutokset.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Asiakasohjelma sammutetaan. Haluatko jatkaa?</translation>
</message>
<message>
@@ -2374,6 +2384,10 @@ Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translatio
<translation type="unfinished">Siirto tarvitsee vielä allekirjoituksia.</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Mutta lompakkoa ei ole ladattu.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Mutta tämä lompakko ei voi allekirjoittaa siirtoja.)</translation>
</message>
@@ -3327,10 +3341,6 @@ Jos saat tämän virheen, pyydä kauppiasta antamaan BIP21-yhteensopiva URI.</tr
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">%1:tä ja korkeampaa siirtokulua pidetään mielettömän korkeana.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Maksupyyntö vanhentui.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3410,14 +3420,6 @@ Jos saat tämän virheen, pyydä kauppiasta antamaan BIP21-yhteensopiva URI.</tr
<translation type="unfinished">Viesti:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Tämä on todentamaton maksupyyntö.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Tämä on todennettu maksupyyntö.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Aseta nimi tälle osoitteelle lisätäksesi sen käytettyjen osoitteiden listalle.</translation>
</message>
@@ -3425,14 +3427,6 @@ Jos saat tämän virheen, pyydä kauppiasta antamaan BIP21-yhteensopiva URI.</tr
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Viesti joka liitettiin bitcoin: URI:iin tallennetaan rahansiirtoon viitteeksi. Tätä viestiä ei lähetetä Bitcoin-verkkoon.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Saaja:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Muistio:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3599,30 +3593,22 @@ Jos saat tämän virheen, pyydä kauppiasta antamaan BIP21-yhteensopiva URI.</tr
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">ristiriidassa maksutapahtumalle, jolla on %1 varmistusta</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/varmistamaton, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">muistialtaassa</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ei muistialtaassa</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">hylätty</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/vahvistamaton</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 vahvistusta</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_fil.ts b/src/qt/locale/bitcoin_fil.ts
index 98081e07c4..c08775bf26 100644
--- a/src/qt/locale/bitcoin_fil.ts
+++ b/src/qt/locale/bitcoin_fil.ts
@@ -324,10 +324,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Error sa pagbabasa %s! Nabasa nang tama ang lahat ng mga key, ngunit ang data ng transaksyon o mga entry sa address book ay maaaring nawawala o hindi tama.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Kamalian: Nabigo ang pakikinig sa mga papasok na koneksyon (ang listen ay nagbalik ng error %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Nabigo ang pagtatantya ng bayad. Hindi pinagana ang Fallbackfee. Maghintay ng ilang mga block o paganahin -fallbackfee.</translation>
</message>
@@ -464,10 +460,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kamalian sa pagbabasa mula sa database, nag-shu-shut down.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Kamalian sa pag-u-upgrade ng chainstate database</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Kamalian: Ang disk space ay mababa para sa %s</translation>
</message>
@@ -636,10 +628,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Hindi suportadong logging category %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Nag-u-upgrade ng UTXO database</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Ang komento ng User Agent (%s) ay naglalaman ng hindi ligtas na mga character.</translation>
</message>
@@ -699,6 +687,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Gumawa ng Bagong Pitaka</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Pagliitin</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Walet:</translation>
</message>
@@ -732,6 +724,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tumanggap</translation>
</message>
<message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;Opsyon</translation>
+ </message>
+ <message>
<source>Encrypt the private keys that belong to your wallet</source>
<translation type="unfinished">I-encrypt ang private keys na kabilang sa iyong walet</translation>
</message>
@@ -847,6 +843,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Walang magagamit na mga walet</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Pangalan ng Pitaka</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">Window</translation>
</message>
@@ -997,6 +998,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kopyahin ang halaga</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopyahin and address</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopyahin ang &amp;label</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopyahin ang &amp;halaga</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Kopyahin ang &amp;ID ng transaksyon at output index</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Kopyahin ang dami</translation>
</message>
@@ -1215,6 +1232,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Kahit na %1 GB na datos ay maiimbak sa direktoryong ito, ito ay lalaki sa pagtagal.</translation>
@@ -1260,10 +1298,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Dahil ngayon lang nilunsad ang programang ito, maaari mong piliin kung saan maiinbak ng %1 ang data nito.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Pagkatapos mong mag-click ng OK, %1 ay magsisimulang mag-download at mag-proseso ng buong blockchain (%2GB) magmula sa pinakaunang transaksyon sa %3 nuong ang %4 ay paunang nilunsad.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">Maraming pangangailangan ang itong paunang sinkronisasyon at maaaring ilantad ang mga problema sa hardware ng iyong computer na hindi dating napansin. Tuwing pagaganahin mo ang %1, ito'y magpapatuloy mag-download kung saan ito tumigil.</translation>
</message>
@@ -1516,10 +1550,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kung magpapakita ng mga tampok ng kontrol ng coin o hindi</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Ang mga nakatakdang opyson sa dialog na ito ay ma-o-override ng command line o sa configuration file:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">OK</translation>
</message>
@@ -1533,14 +1563,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Kumpirmahin ang pag-reset ng mga opsyon</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Kailangan i-restart ang kliyente upang ma-activate ang mga pagbabago.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Ang kliyente ay papatayin. Nais mo bang magpatuloy?</translation>
</message>
<message>
@@ -1972,6 +2005,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Labas:</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;Kopyahin and address</translation>
+ </message>
+ <message>
<source>&amp;Disconnect</source>
<translation type="unfinished">Idiskonekta</translation>
</message>
@@ -2107,6 +2145,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kopyahin ang URI</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopyahin and address</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopyahin ang &amp;label</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopyahin ang &amp;halaga</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">Hindi magawang ma-unlock ang walet.</translation>
</message>
@@ -2392,10 +2442,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Ang bayad na mas mataas sa %1 ay itinuturing na napakataas na bayad.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Ang hiling ng bayad ay nag-expire na.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2471,14 +2517,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Mensahe:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Ito ay isang unauthenticated na hiling ng bayad.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Ito ay isang authenticated na hiling ng bayad.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Mag-enter ng label para sa address na ito upang idagdag ito sa listahan ng mga gamit na address.</translation>
</message>
@@ -2486,11 +2524,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Mensahe na nakalakip sa bitcoin: URI na kung saan maiimbak kasama ang transaksyon para sa iyong sanggunian. Tandaan: Ang mensaheng ito ay hindi ipapadala sa network ng Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Magbayad Sa:</translation>
- </message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -2637,30 +2671,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">sumalungat sa isang transaksyon na may %1 pagkumpirma</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/hindi nakumpirma, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">nasa memory pool</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">wala sa memory pool</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">inabandona</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/hindi nakumpirma</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 pagkumpirma</translation>
</message>
<message>
@@ -2932,6 +2958,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Minimum na halaga</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopyahin and address</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopyahin ang &amp;label</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopyahin ang &amp;halaga</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">I-export ang Kasaysayan ng Transaksyon</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts
index cedecd674e..9b6d18b337 100644
--- a/src/qt/locale/bitcoin_fr.ts
+++ b/src/qt/locale/bitcoin_fr.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">Cliquer à droite pour modifier l’adresse ou l’étiquette</translation>
+ <translation type="unfinished">‎Cliquez avec le bouton droit de la souris pour modifier l’adresse ou l’étiquette‎</translation>
</message>
<message>
<source>Create a new address</source>
@@ -72,8 +72,8 @@
<message>
<source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
Signing is only possible with addresses of the type 'legacy'.</source>
- <translation type="unfinished">Ce sont vos adresses Bitcoin pour recevoir des paiements. Utilisez le bouton « Créer une nouvelle adresse de réception » dans l’onglet Recevoir afin de créer de nouvelles adresses.
-Il n’est possible de signer qu’avec les adresses de type « legacy ».</translation>
+ <translation type="unfinished">Il s'agit de vos adresses Bitcoin pour la réception des paiements. Utilisez le bouton "Créer une nouvelle adresse de réception" dans l'onglet "Recevoir" pour créer de nouvelles adresses.
+La signature n'est possible qu'avec les adresses de type "patrimoine".</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -229,7 +229,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
- <translation type="unfinished">Avertissement : La touche Verr. Maj. est activée !</translation>
+ <translation type="unfinished">Avertissement : La touche Verr. Maj. est activée</translation>
</message>
</context>
<context>
@@ -246,8 +246,12 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Le fichier de configuration %1 est peut-être corrompu ou invalide.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
- <translation type="unfinished">Exception fugitive</translation>
+ <translation type="unfinished">Exception excessive</translation>
</message>
<message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
@@ -255,7 +259,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Internal error</source>
- <translation type="unfinished">Erreur interne</translation>
+ <translation type="unfinished">erreur interne</translation>
</message>
<message>
<source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
@@ -303,6 +307,10 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">Saisir une adresse Bitcoin (p. ex. %1)</translation>
</message>
<message>
+ <source>Ctrl+W</source>
+ <translation type="unfinished">Ctrl-W</translation>
+ </message>
+ <message>
<source>Unroutable</source>
<translation type="unfinished">Non routable</translation>
</message>
@@ -364,7 +372,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform>%n seconde</numerusform>
+ <numerusform>%n second</numerusform>
<numerusform>%n secondes</numerusform>
</translation>
</message>
@@ -403,8 +411,8 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform>%n an</numerusform>
- <numerusform>%n ans</numerusform>
+ <numerusform>%n année</numerusform>
+ <numerusform>%n années</numerusform>
</translation>
</message>
<message>
@@ -444,7 +452,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation type="unfinished">La valeur -maxtxfee est très élevée ! Des frais aussi élevés pourraient être payés en une seule transaction.</translation>
+ <translation type="unfinished">La valeur -maxtxfee est très élevée. Des frais aussi élevés pourraient être payés en une seule transaction.</translation>
</message>
<message>
<source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
@@ -456,7 +464,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>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>
- <translation type="unfinished">Impossible de mettre à niveau un porte-monnaie divisé non-HD de la version %i vers la version %i sans mettre à niveau pour prendre en charge la réserve de clés antérieure à la division. Veuillez utiliser la version %i ou ne pas indiquer de version.</translation>
+ <translation type="unfinished">Impossible de mettre à niveau un porte-monnaie divisé non-HD de la version %i vers la version %i sans mise à niveau pour prendre en charge la réserve de clés antérieure à la division. Veuillez utiliser la version %i ou ne pas indiquer de version.</translation>
</message>
<message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
@@ -468,23 +476,23 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
- <translation type="unfinished">Erreur de lecture de %s : soit les données de la transaction manquent soit elles sont incorrectes. Réanalysez le porte-monnaie.</translation>
+ <translation type="unfinished">Erreur de lecture de %s : soit les données de la transaction manquent soit elles sont incorrectes. Réanalyse du porte-monnaie.</translation>
</message>
<message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
<translation type="unfinished">Erreur : L’enregistrement du format du fichier de vidage est incorrect. Est « %s », mais « format » est attendu. </translation>
</message>
<message>
+ <source>Error: Dumpfile identifier record is incorrect. Got "%s", expected "%s".</source>
+ <translation type="unfinished">Erreur : L’enregistrement de l’identificateur du fichier de vidage est incorrect. Est « %s », mais « %s » est attendu. </translation>
+ </message>
+ <message>
<source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
<translation type="unfinished">Erreur : La version du fichier de vidage n’est pas prise en charge. Cette version de bitcoin-wallet ne prend en charge que les fichiers de vidage version 1. Le fichier de vidage obtenu est de la version %s.</translation>
</message>
<message>
<source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
- <translation type="unfinished">Erreur : les porte-monnaie hérités ne prennent en charge que les types d’adresse « legacy », « p2sh-segwit », et « bech32 ».</translation>
- </message>
- <message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Erreur : L’écoute des connexions entrantes a échoué (l’écoute a retourné l’erreur %s)</translation>
+ <translation type="unfinished">Erreur : les porte-monnaie hérités ne prennent en charge que les types d’adresse « legacy », « p2sh-segwit », et « bech32 »</translation>
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
@@ -532,7 +540,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
- <translation type="unfinished">Élagage : la dernière synchronisation de porte-monnaie va par-delà les données élaguées. Vous devez -reindex (réindexer, télécharger de nouveau toute la chaîne de blocs en cas de nœud élagué)</translation>
+ <translation type="unfinished">Élagage : la dernière synchronisation de porte-monnaie va par-delà les données élaguées. Vous devez -reindex (réindexer, télécharger de nouveau toute la chaîne de blocs en cas de nœud élagué)</translation>
</message>
<message>
<source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
@@ -544,19 +552,19 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
- <translation type="unfinished">La base de données d’indexation des blocs comprend un « txindex » hérité. Pour libérer l’espace disque occupé, exécuter un -reindex complet ou ignorez cette erreur. Ce message d’erreur ne sera pas affiché de nouveau.</translation>
+ <translation type="unfinished">La base de données d’indexation des blocs comprend un « txindex » hérité. Pour libérer l’espace disque occupé, exécutez un -reindex complet ou ignorez cette erreur. Ce message d’erreur ne sera pas affiché de nouveau.</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation type="unfinished">Le montant transactionnel est trop bas pour être envoyé une fois que les frais ont été déduits</translation>
+ <translation type="unfinished">Le montant de la transaction est trop bas pour être envoyé une fois que les frais ont été déduits</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">Cette erreur pourrait survenir si ce porte-monnaie n’avait pas été fermé proprement et s’il avait été chargé en dernier avec une nouvelle version de Berkeley DB. Si c’est le cas, veuillez utiliser le logiciel qui a chargé ce porte-monnaie en dernier.</translation>
+ <translation type="unfinished">Cette erreur pourrait survenir si ce porte-monnaie n’a pas été fermé proprement et s’il a été chargé en dernier avec une nouvelle version de Berkeley DB. Si c’est le cas, veuillez utiliser le logiciel qui a chargé ce porte-monnaie en dernier.</translation>
</message>
<message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
- <translation type="unfinished">Ceci est une préversion de test - son utilisation est entièrement à vos risques - ne pas l’utiliser pour miner ou pour des applications marchandes</translation>
+ <translation type="unfinished">Ceci est une préversion de test — son utilisation est entièrement à vos risques — ne l’utilisez pour miner ou pour des applications marchandes</translation>
</message>
<message>
<source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
@@ -579,12 +587,16 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">Impossible de relire les blocs. Vous devrez reconstruire la base de données avec -reindex-chainstate.</translation>
</message>
<message>
+ <source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
+ <translation type="unfinished">Le format de fichier porte-monnaie « %s » indiqué est inconnu. Veuillez soit indiquer « bdb » soit « sqlite ».</translation>
+ </message>
+ <message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
<translation type="unfinished">Avertissement : Le format du fichier de vidage de porte-monnaie « %s » ne correspond pas au format « %s » indiqué dans la ligne de commande.</translation>
</message>
<message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <translation type="unfinished">Avertissement : Des clés privées ont été détectées dans le porte-monnaie {%s}, dont les clés privées sont désactivées</translation>
+ <translation type="unfinished">Avertissement : Des clés privées ont été détectées dans le porte-monnaie {%s} avec des clés privées désactivées</translation>
</message>
<message>
<source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
@@ -600,7 +612,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>%s is set very high!</source>
- <translation type="unfinished">La valeur %s est très élevée !</translation>
+ <translation type="unfinished">La valeur %s est très élevée</translation>
</message>
<message>
<source>-maxmempool must be at least %d MB</source>
@@ -631,20 +643,40 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">La mise à niveau -txindex lancée par une version précédente ne peut pas être achevée. Redémarrez la version précédente ou exécutez un -reindex complet.</translation>
</message>
<message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s a demandé d’écouter sur le port %u. Ce port est considéré comme « mauvais » et il est par conséquent improbable que des pairs Bitcoin Core y soient connectés. Consulter doc/p2p-bad-ports.md pour plus de précisions et une liste complète.</translation>
+ </message>
+ <message>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
- <translation type="unfinished">Il est impossible de fournir des connexions particulières et en même temps demander à addrman de trouver les connexions sortantes.</translation>
+ <translation type="unfinished">Il est impossible d’indiquer des connexions précises et en même temps de demander à addrman de trouver les connexions sortantes.</translation>
</message>
<message>
<source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
<translation type="unfinished">Erreur de chargement de %s : le porte-monnaie signataire externe est chargé sans que la prise en charge de signataires externes soit compilée</translation>
</message>
<message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Échec de renommage du fichier peers.dat invalide. Veuillez le déplacer ou le supprimer, puis réessayer.</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+Impossible de nettoyer la migration en erreur</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Impossible de restaurer la sauvegarde du portefeuille.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Paramètre de configuration pour %s qui n’est appliqué sur le réseau %s que s’il se trouve dans la section [%s].</translation>
</message>
<message>
<source>Copyright (C) %i-%i</source>
- <translation type="unfinished">Tous droits réservés (C) %i-%i</translation>
+ <translation type="unfinished">Tous droits réservés © %i à %i</translation>
</message>
<message>
<source>Corrupted block database detected</source>
@@ -660,7 +692,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Disk space is too low!</source>
- <translation type="unfinished">L’espace disque est trop faible !</translation>
+ <translation type="unfinished">L’espace disque est trop faible</translation>
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
@@ -672,7 +704,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Dump file %s does not exist.</source>
- <translation type="unfinished">Le fichier de vidage %s n’existe pas</translation>
+ <translation type="unfinished">Le fichier de vidage %s n’existe pas.</translation>
</message>
<message>
<source>Error creating %s</source>
@@ -684,7 +716,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Error initializing wallet database environment %s!</source>
- <translation type="unfinished">Erreur d’initialisation de l’environnement de la base de données du porte-monnaie %s !</translation>
+ <translation type="unfinished">Erreur d’initialisation de l’environnement de la base de données du porte-monnaie %s </translation>
</message>
<message>
<source>Error loading %s</source>
@@ -712,17 +744,13 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Error reading from database, shutting down.</source>
- <translation type="unfinished">Erreur de lecture de la base de données, fermeture en cours.</translation>
+ <translation type="unfinished">Erreur de lecture de la base de données, fermeture en cours</translation>
</message>
<message>
<source>Error reading next record from wallet database</source>
<translation type="unfinished">Erreur de lecture de l’enregistrement suivant de la base de données du porte-monnaie</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Erreur de mise à niveau de la base de données d’état de la chaîne</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Erreur : Impossible de créer le curseur dans la base de données</translation>
</message>
@@ -752,19 +780,31 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Error: No %s addresses available.</source>
- <translation type="unfinished">Erreur : Aucune adresse %s n’est disponible</translation>
+ <translation type="unfinished">Erreur : Aucune adresse %s n’est disponible.</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Erreur : ce portefeuille utilise déjà SQLite</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Erreur : impossible de faire une sauvegarde de votre portefeuille</translation>
</message>
<message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">Erreur : Impossible d’analyser la version %u en tant que uint32_t</translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Erreur : impossible de lire tous les enregistrement dans la base de données</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
<translation type="unfinished">Erreur : Impossible d’écrire l’enregistrement dans le nouveau porte-monnaie</translation>
</message>
<message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation type="unfinished">Échec d'écoute sur n’importe quel port. Utiliser -listen=0 si vous voulez le faire.</translation>
+ <translation type="unfinished">Échec d'écoute sur tous les ports. Si cela est voulu, utiliser -listen=0.</translation>
</message>
<message>
<source>Failed to rescan the wallet during initialization</source>
@@ -791,6 +831,10 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">Bloc de genèse incorrect ou introuvable. Mauvais datadir pour le réseau ?</translation>
</message>
<message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation type="unfinished">Échec d’initialisation du test de cohérence. %s est en cours de fermeture.</translation>
+ </message>
+ <message>
<source>Input not found or already spent</source>
<translation type="unfinished">L’entrée est introuvable ou a déjà été dépensée</translation>
</message>
@@ -800,7 +844,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Invalid -i2psam address or hostname: '%s'</source>
- <translation type="unfinished">L’adresse ou le nom d’hôte -i2psam est invalide :« %s »</translation>
+ <translation type="unfinished">L’adresse ou le nom d’hôte -i2psam est invalide : « %s »</translation>
</message>
<message>
<source>Invalid -onion address or hostname: '%s'</source>
@@ -828,7 +872,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation type="unfinished">Le montant est invalide pour -paytxfee=&lt;montant&gt; : « %s » (doit être au moins %s)</translation>
+ <translation type="unfinished">Le montant est invalide pour -paytxfee=&lt;amount&gt; : « %s » (doit être au moins %s)</translation>
</message>
<message>
<source>Invalid netmask specified in -whitelist: '%s'</source>
@@ -836,7 +880,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Loading P2P addresses…</source>
- <translation type="unfinished">Chargement des adresses P2P…</translation>
+ <translation type="unfinished">Chargement des adresses P2P…</translation>
</message>
<message>
<source>Loading banlist…</source>
@@ -860,31 +904,23 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Need to specify a port with -whitebind: '%s'</source>
- <translation type="unfinished">Un port doit être précisé avec -whitebind : « %s »</translation>
+ <translation type="unfinished">Un port doit être indiqué avec -whitebind : « %s »</translation>
</message>
<message>
<source>No addresses available</source>
<translation type="unfinished">Aucune adresse n’est disponible</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Aucun serveur mandataire n’est indiqué. Utilisez -proxy=&lt;ip&gt; ou -proxy=&lt;ip:port&gt;</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Trop peu de descripteurs de fichiers sont disponibles.</translation>
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
- <translation type="unfinished">L’élagage ne peut pas être configuré avec une valeur négative.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Le mode élagage n’est pas compatible avec -coinstatsindex.</translation>
+ <translation type="unfinished">L’élagage ne peut pas être configuré avec une valeur négative</translation>
</message>
<message>
<source>Prune mode is incompatible with -txindex.</source>
- <translation type="unfinished">Le mode élagage n’est pas compatible avec -txindex.</translation>
+ <translation type="unfinished">Le mode élagage n’est pas compatible avec -txindex</translation>
</message>
<message>
<source>Pruning blockstore…</source>
@@ -916,11 +952,11 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
- <translation type="unfinished">SQLiteDatabase : l’ID de l’application est inattendu. %u était attendu, %u été retourné</translation>
+ <translation type="unfinished">SQLiteDatabase : l’ID de l’application est inattendu. %u attendu, %u retourné</translation>
</message>
<message>
<source>Section [%s] is not recognized.</source>
- <translation type="unfinished">La section [%s] n’est pas reconnue.</translation>
+ <translation type="unfinished">La section [%s] n’est pas reconnue</translation>
</message>
<message>
<source>Signing transaction failed</source>
@@ -940,7 +976,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Specified blocks directory "%s" does not exist.</source>
- <translation type="unfinished">Le répertoire des blocs indiqué « %s » n’existe pas.</translation>
+ <translation type="unfinished">Le répertoire des blocs indiqué « %s » n’existe pas</translation>
</message>
<message>
<source>Starting network threads…</source>
@@ -952,7 +988,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>The specified config file %s does not exist</source>
- <translation type="unfinished">Le fichier de configuration %s n’existe pas</translation>
+ <translation type="unfinished">Le fichier de configuration indiqué %s n’existe pas</translation>
</message>
<message>
<source>The transaction amount is too small to pay the fee</source>
@@ -1004,17 +1040,21 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation type="unfinished">Impossible de se lier à %s sur cet ordinateur (bind a retourné l’erreur %s)</translation>
+ <translation type="unfinished">Impossible de se lier à %s sur cet ordinateur (la liaison a retourné l’erreur %s)</translation>
</message>
<message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation type="unfinished">Impossible de se lier à %s sur cet ordinateur. %s fonctionne probablement déjà.</translation>
+ <translation type="unfinished">Impossible de se lier à %s sur cet ordinateur. %s fonctionne probablement déjà</translation>
</message>
<message>
<source>Unable to create the PID file '%s': %s</source>
<translation type="unfinished">Impossible de créer le fichier PID « %s » : %s</translation>
</message>
<message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">Impossible de trouver UTXO pour l'entrée externe</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation type="unfinished">Impossible de générer les clés initiales</translation>
</message>
@@ -1035,16 +1075,20 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">Impossible de démarrer le serveur HTTP. Consulter le journal de débogage pour plus de précisions.</translation>
</message>
<message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">Impossible de décharger le portefeuille avant de migrer</translation>
+ </message>
+ <message>
<source>Unknown -blockfilterindex value %s.</source>
- <translation type="unfinished">Valeur -blockfilterindex inconnue %s.</translation>
+ <translation type="unfinished">La valeur -blockfilterindex %s est inconnue.</translation>
</message>
<message>
<source>Unknown address type '%s'</source>
- <translation type="unfinished">Type d’adresse inconnu « %s »</translation>
+ <translation type="unfinished">Le type d’adresse « %s » est inconnu</translation>
</message>
<message>
<source>Unknown change type '%s'</source>
- <translation type="unfinished">Le type de monnaie est inconnu « %s »</translation>
+ <translation type="unfinished">Le type de monnaie « %s » est inconnu</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
@@ -1056,15 +1100,11 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">La catégorie de journalisation n’est pas prise en charge %s=%s.</translation>
- </message>
- <message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Mise à niveau de la base de données UTXO</translation>
+ <translation type="unfinished">La catégorie de journalisation %s=%s n’est pas prise en charge</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
- <translation type="unfinished">Le commentaire de l’agent utilisateur (%s) comporte des caractères dangereux.</translation>
+ <translation type="unfinished">Le commentaire de l’agent utilisateur (%s) comporte des caractères dangereux</translation>
</message>
<message>
<source>Verifying blocks…</source>
@@ -1172,7 +1212,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>&amp;Backup Wallet…</source>
- <translation type="unfinished">&amp;auvegarder le porte-monnaie…</translation>
+ <translation type="unfinished">&amp;Sauvegarder le porte-monnaie…</translation>
</message>
<message>
<source>&amp;Change Passphrase…</source>
@@ -1184,7 +1224,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Signer les messages avec vos adresses Bitcoin pour prouver que vous les détenez</translation>
+ <translation type="unfinished">Signer les messages avec vos adresses Bitcoin pour prouver que vous les détenez</translation>
</message>
<message>
<source>&amp;Verify message…</source>
@@ -1196,7 +1236,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>&amp;Load PSBT from file…</source>
- <translation type="unfinished">&amp;Charger une TBSP d’un fichier…</translation>
+ <translation type="unfinished">&amp;Charger la TBSP d’un fichier…</translation>
</message>
<message>
<source>Open &amp;URI…</source>
@@ -1204,15 +1244,15 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Close Wallet…</source>
- <translation type="unfinished">Fermer le portefeuille...</translation>
+ <translation type="unfinished">Fermer le porte-monnaie…</translation>
</message>
<message>
<source>Create Wallet…</source>
- <translation type="unfinished">Créer le portefeuille...</translation>
+ <translation type="unfinished">Créer un porte-monnaie…</translation>
</message>
<message>
<source>Close All Wallets…</source>
- <translation type="unfinished">Fermer tous les portefeuilles...</translation>
+ <translation type="unfinished">Fermer tous les porte-monnaie…</translation>
</message>
<message>
<source>&amp;File</source>
@@ -1232,7 +1272,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Syncing Headers (%1%)…</source>
- <translation type="unfinished">Synchronisation des en-têtes (%1)…</translation>
+ <translation type="unfinished">Synchronisation des en-têtes (%1%)…</translation>
</message>
<message>
<source>Synchronizing with network…</source>
@@ -1273,8 +1313,8 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform>%n bloc d’historique transactionnel a été traité.</numerusform>
- <numerusform>%n blocs d’historique transactionnel ont été traités.</numerusform>
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message>
@@ -1283,7 +1323,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Catching up…</source>
- <translation type="unfinished">Rattrapage en cours…</translation>
+ <translation type="unfinished">Rattrapage…</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
@@ -1354,12 +1394,22 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">Fermer le porte-monnaie</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Restaurer un portefeuille...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Restaurer un portefeuille depuis un fichier de récupération</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Fermer tous les porte-monnaie</translation>
</message>
<message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation type="unfinished">Afficher le message d’aide de %1 pour obtenir la liste des options possibles de ligne de commande Bitcoin</translation>
+ <translation type="unfinished">Afficher le message d’aide de %1 pour obtenir la liste des options possibles en ligne de commande Bitcoin</translation>
</message>
<message>
<source>&amp;Mask values</source>
@@ -1378,6 +1428,26 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">Aucun porte-monnaie n’est disponible</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Données du porte-monnaie</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Charger la Sauvegarde du Portefeuille</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Restaurer le portefeuille</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nom du porte-monnaie</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Fenêtre</translation>
</message>
@@ -1405,8 +1475,8 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform>%n connexion active avec le réseau Bitcoin.</numerusform>
- <numerusform>%n connexions actives avec le réseau Bitcoin.</numerusform>
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message>
@@ -1430,6 +1500,10 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">Activer l’activité réseau</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Pré-synchronisation des en-têtes (%1%)...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Erreur : %1</translation>
</message>
@@ -1684,7 +1758,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<source>Can't list signers</source>
<translation type="unfinished">Impossible de lister les signataires</translation>
</message>
-</context>
+ </context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1724,6 +1798,29 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Restaurer le portefeuille</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Restauration du Portefeuille &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Échec de la restauration du portefeuille</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Message de restauration du portefeuille</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1898,13 +1995,26 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</context>
<context>
<name>Intro</name>
- <message>
- <source>%1 GB of space available</source>
- <translation type="unfinished">%1 Go d’espace disponible</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n Go d’espace disponible</numerusform>
+ <numerusform>%n Go d’espace disponible</numerusform>
+ </translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(sur %1 Go nécessaires)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1918,8 +2028,8 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform>(suffisant pour restaurer les sauvegardes âgées de %n jour)</numerusform>
- <numerusform>(suffisant pour restaurer les sauvegardes âgées de %n jours)</numerusform>
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message>
@@ -1951,10 +2061,6 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">Comme le logiciel est lancé pour la première fois, vous pouvez choisir où %1 stockera ses données.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Quand vous cliquerez sur Valider, %1 commencera à télécharger et à traiter l’intégralité de la chaîne de blocs %4 (%2 Go) en débutant avec les transactions les plus anciennes de %3, quand %4 a été lancé initialement.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Limiter l’espace de stockage de chaîne de blocs à</translation>
</message>
@@ -2025,7 +2131,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Unknown…</source>
- <translation type="unfinished">Inconnus…</translation>
+ <translation type="unfinished">Inconnu…</translation>
</message>
<message>
<source>calculating…</source>
@@ -2063,7 +2169,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Inconnu. Synchronisation des en-têtes (%1, %2 %)…</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2336,7 +2442,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
- <translation type="unfinished">Utiliser un mandataire SOCKS&amp;5 séparé pour atteindre les pairs par les services oignon de Tor.</translation>
+ <translation type="unfinished">Utiliser un mandataire SOCKS&amp;5 séparé pour atteindre les pairs par les services oignon de Tor :</translation>
</message>
<message>
<source>Monospaced font in the Overview tab:</source>
@@ -2351,10 +2457,6 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
<translation type="unfinished">correspondance la plus proche « %1 »</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Les options définies dans cette boîte de dialogue sont remplacées par la ligne de commande ou par le fichier de configuration :</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;Valider</translation>
</message>
@@ -2377,14 +2479,22 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirmer la réinitialisation des options</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Le redémarrage du client est exigé pour activer les changements.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Les paramètres courants seront sauvegardés à "%1".</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Le client sera arrêté. Voulez-vous continuer ?</translation>
</message>
<message>
@@ -2553,7 +2663,7 @@ Il n’est possible de signer qu’avec les adresses de type « legacy ».</tr
</message>
<message>
<source>Unknown error processing transaction.</source>
- <translation type="unfinished">Erreur inconnue lors de traitement de la transaction.</translation>
+ <translation type="unfinished">Erreur inconnue lors de traitement de la transaction</translation>
</message>
<message>
<source>Transaction broadcast successfully! Transaction ID: %1</source>
@@ -2659,7 +2769,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation type="unfinished">L’URI ne peut pas être analysée ! Cela peut être causé par une adresse Bitcoin invalide ou par des paramètres d’URI mal formés.</translation>
+ <translation type="unfinished">L’URI ne peut pas être analysée. Cela peut être causé par une adresse Bitcoin invalide ou par des paramètres d’URI mal formés.</translation>
</message>
<message>
<source>Payment request file handling</source>
@@ -2679,6 +2789,11 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">Pair</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Âge</translation>
+ </message>
+ <message>
<source>Sent</source>
<extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
<translation type="unfinished">Envoyé</translation>
@@ -2865,29 +2980,22 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Reliez ou non des adresses à ce pair.</translation>
</message>
<message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Relais d’adresses</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">Nombre total d’adresses traitées, excluant celles abandonnées en raison de la limite de débit.</translation>
- </message>
- <message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">Adresses traitées</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">Nombre total d’adresses abandonnées en raison de la limite de débit.</translation>
- </message>
- <message>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">Adresses ciblées par la limite de débit</translation>
</message>
<message>
@@ -2932,7 +3040,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Wants Tx Relay</source>
- <translation type="unfinished">Veut Tx relai</translation>
+ <translation type="unfinished">Veut relayer les transactions</translation>
</message>
<message>
<source>High bandwidth BIP152 compact block relay: %1</source>
@@ -3358,7 +3466,7 @@ Pour plus de précisions sur cette console, tapez %6.
</message>
<message>
<source>Insufficient funds!</source>
- <translation type="unfinished">Les fonds sont insuffisants !</translation>
+ <translation type="unfinished">Les fonds sont insuffisants</translation>
</message>
<message>
<source>Quantity:</source>
@@ -3663,15 +3771,18 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
</message>
<message>
<source>Transaction creation failed!</source>
- <translation type="unfinished">Échec de création de la transaction !</translation>
+ <translation type="unfinished">Échec de création de la transaction</translation>
</message>
<message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Des frais supérieurs à %1 sont considérés comme ridiculement élevés.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">La demande de paiement a expiré.</translation>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
@@ -3710,7 +3821,7 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
</message>
<message>
<source>Choose previously used address</source>
- <translation type="unfinished">Choisir une adresse déjà utilisée</translation>
+ <translation type="unfinished">Choisir une adresse utilisée précédemment</translation>
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
@@ -3718,7 +3829,7 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
</message>
<message>
<source>Paste address from clipboard</source>
- <translation type="unfinished">Coller l’adresse du presse-papiers</translation>
+ <translation type="unfinished">Collez l’adresse du presse-papiers</translation>
</message>
<message>
<source>Remove this entry</source>
@@ -3745,14 +3856,6 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
<translation type="unfinished">Message :</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Cette demande de paiement n’est pas authentifiée.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Cette demande de paiement est authentifiée.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Saisir une étiquette pour cette adresse afin de l’ajouter à la liste d’adresses utilisées</translation>
</message>
@@ -3760,14 +3863,6 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Un message qui était joint à l’URI bitcoin: et qui sera stocké avec la transaction pour référence. Note : Ce message ne sera pas envoyé par le réseau Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Payer à :</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Mémo :</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3804,7 +3899,7 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
</message>
<message>
<source>Paste address from clipboard</source>
- <translation type="unfinished">Coller l’adresse du presse-papiers</translation>
+ <translation type="unfinished">Collez l’adresse du presse-papiers</translation>
</message>
<message>
<source>Enter the message you want to sign here</source>
@@ -3927,7 +4022,7 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
</message>
<message>
<source>press q to shutdown</source>
- <translation type="unfinished">appuyer sur q pour fermer</translation>
+ <translation type="unfinished">Appuyer sur q pour fermer</translation>
</message>
</context>
<context>
@@ -3941,26 +4036,17 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">est en conflit avec une transaction ayant %1 confirmations</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/non confirmées, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">dans la réserve de mémoire</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">pas dans la réserve de mémoire</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abandonnée</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/non confirmée</translation>
</message>
<message>
@@ -4002,8 +4088,8 @@ Note : Les frais étant calculés par octet, un taux de frais de « 100 satoshi
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform>arrivera à maturité dans %n bloc</numerusform>
- <numerusform>arrivera à maturité dans %n blocs</numerusform>
+ <numerusform>matures dans %n bloc supplémentaire</numerusform>
+ <numerusform>matures dans %n blocs supplémentaires</numerusform>
</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_ga.ts b/src/qt/locale/bitcoin_ga.ts
index 3b9c3fdceb..ee230fb909 100644
--- a/src/qt/locale/bitcoin_ga.ts
+++ b/src/qt/locale/bitcoin_ga.ts
@@ -381,10 +381,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<translation type="unfinished">Earráid ag léamh %s! Léigh gach eochair i gceart, ach d’fhéadfadh sonraí idirbhirt nó iontrálacha leabhar seoltaí a bheidh in easnamh nó mícheart.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Earráid: Theip ar éisteacht le naisc teacht-isteach (chuir éist earráid %s ar ais)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Theip ar mheastachán táillí. Tá fallbackfee díchumasaithe. Fan cúpla bloc nó cumasaigh -fallbackfee.</translation>
</message>
@@ -557,10 +553,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<translation type="unfinished">Earráid ag léamh ón mbunachar sonraí, ag múchadh.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Earráid ag uasghrádú bunachar sonraí chainstate</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Earráid: Tá spás ar diosca íseal do %s</translation>
</message>
@@ -637,10 +629,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<translation type="unfinished">Is gá port a shainiú le -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Níl seachfhreastalaí sainithe. Úsáid -proxy=&lt;ip&gt; nó -proxy=&lt;ip:port&gt;.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Níl dóthain tuairisceoirí comhaid ar fáil.</translation>
</message>
@@ -785,10 +773,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<translation type="unfinished">Catagóir logáil gan tacaíocht %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Ag uasghrádú bunachar sonraí UTXO</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Tá carachtair neamhshábháilte i nóta tráchta (%s) Gníomhaire Úsáideora.</translation>
</message>
@@ -1017,6 +1001,11 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<translation type="unfinished">Níl aon sparán ar fáil</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Ainm Sparán</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Fuinneog</translation>
</message>
@@ -1455,6 +1444,30 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Ar a laghad stórálfar %1 GB de shonraí sa comhadlann seo, agus fásfaidh sé le himeacht ama.</translation>
@@ -1501,10 +1514,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<translation type="unfinished">Mar gurb é seo an chéad uair a lainseáil an clár, is féidir leat a roghnú cá stórálfaidh %1 a chuid sonraí.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Nuair a chliceálann tú Togha, tosóidh %1 ag íoslódáil agus ag próiseáil an blocshlabhra iomlán %4 (%2GB) ag tosú leis na hidirbhearta is luaithe %3 nuair a lainseáil %4 i dtosach.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">Teastaíonn an blocshlabhra iomlán a íoslódáil arís chun an socrú seo a fhilleadh. Tá sé níos sciobtha an slabhra iomlán a íoslódáil ar dtús agus é a bhearradh níos déanaí. Díchumasaíodh roinnt ardgnéithe.</translation>
</message>
@@ -1777,10 +1786,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<translation type="unfinished">Úsáid seachfhreastalaí SOCKS5 ar leith chun sroicheadh piaraí trí sheirbhísí Tor oinniún:</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Tá na roghanna socraithe sa dialóg seo sáraithe ag líne na n-orduithe nó sa chomhad cumraíochta:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;Togha</translation>
</message>
@@ -1798,14 +1803,17 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Deimhnigh athshocrú roghanna</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Atosú cliant ag teastáil chun athruithe a ghníomhachtú.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Múchfar an cliant. Ar mhaith leat dul ar aghaidh?</translation>
</message>
<message>
@@ -2827,10 +2835,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Meastar gur táille áiféiseach ard í táille níos airde ná %1.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Iarratas íocaíocht éagtha.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2911,14 +2915,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<translation type="unfinished">Teachtaireacht:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Iarratas íocaíocht neamhfíordheimhnithe é seo.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Iarratas íocaíocht fíordheimhnithe é seo.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Iontráil lipéad don seoladh seo chun é a chur le liosta na seoltaí úsáidte</translation>
</message>
@@ -2926,14 +2922,6 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Teachtaireacht a bhí ceangailte leis an bitcoin: URI a stórálfar leis an idirbheart le haghaidh do thagairt. Nóta: Ní sheolfar an teachtaireacht seo thar líonra Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Ãoc chuig:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Meamram:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3093,30 +3081,22 @@ Ní féidir síniú ach le seoltaí 'oidhreachta'.</translation>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">faoi choimhlint le idirbheart le %1 dearbhuithe</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/neamhdheimhnithe, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">i linn cuimhne</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ní i linn cuimhne</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">tréigthe</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/neamhdheimhnithe</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 dearbhuithe</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_gd.ts b/src/qt/locale/bitcoin_gd.ts
index 53e45eff30..63a59d6fe8 100644
--- a/src/qt/locale/bitcoin_gd.ts
+++ b/src/qt/locale/bitcoin_gd.ts
@@ -113,6 +113,11 @@
<source>Information</source>
<translation type="unfinished">Fiosrachadh</translation>
</message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Ainm Wallet</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -141,6 +146,33 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_gl.ts b/src/qt/locale/bitcoin_gl.ts
index c032ef7407..72cf96a006 100644
--- a/src/qt/locale/bitcoin_gl.ts
+++ b/src/qt/locale/bitcoin_gl.ts
@@ -706,6 +706,27 @@ Firmar é posible unicamente con enderezos de tipo 'legacy'.</translation>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -856,6 +877,7 @@ Firmar é posible unicamente con enderezos de tipo 'legacy'.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirmar opcións de restaurar</translation>
</message>
<message>
@@ -1221,10 +1243,6 @@ Firmar é posible unicamente con enderezos de tipo 'legacy'.</translation>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
<translation type="unfinished">O total sobrepasa o teu balance cando se inclúe a tarifa de transacción %1.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Solicitude de pagamento expirada.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -1279,10 +1297,6 @@ Firmar é posible unicamente con enderezos de tipo 'legacy'.</translation>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduce unha etiqueta para esta dirección para engadila á listaxe de direccións empregadas</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pagar A:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1403,10 +1417,12 @@ Firmar é posible unicamente con enderezos de tipo 'legacy'.</translation>
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/sen confirmar</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 confirmacións</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_gl_ES.ts b/src/qt/locale/bitcoin_gl_ES.ts
index 87277251d1..2b382cd922 100644
--- a/src/qt/locale/bitcoin_gl_ES.ts
+++ b/src/qt/locale/bitcoin_gl_ES.ts
@@ -484,6 +484,11 @@
<translation type="unfinished">Non hai carteiras dispoñibles</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nome da Carteira</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Xanela</translation>
</message>
@@ -823,6 +828,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_gu.ts b/src/qt/locale/bitcoin_gu.ts
index 857c06e12d..861171c391 100644
--- a/src/qt/locale/bitcoin_gu.ts
+++ b/src/qt/locale/bitcoin_gu.ts
@@ -239,6 +239,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_ha.ts b/src/qt/locale/bitcoin_ha.ts
new file mode 100644
index 0000000000..6b6356d15e
--- /dev/null
+++ b/src/qt/locale/bitcoin_ha.ts
@@ -0,0 +1,185 @@
+<TS version="2.1" language="ha">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation type="unfinished">Danna dama don gyara adireshi ko labil</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation type="unfinished">Ƙirƙiri sabon adireshi</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation type="unfinished">Sabontawa</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation type="unfinished">Kwafi adireshin da aka zaɓa a halin yanzu domin yin amfani dashi</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">Share adireshin da aka zaɓa a halin yanzu daga jerin </translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">Shigar da adireshi ko lakabi don bincika</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Fitar da bayanan da ke cikin shafin na yanzu zuwa fayil</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp; Fitarwa</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">&amp;Sharewa</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">Zaɓi adireshin don karɓar kuɗi internet da shi</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation type="unfinished">Adireshi da za a karba dashi</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">WaÉ—annan adiresoshin Bitcoin ne don tura kuÉ—i bitcoin . ka tabbatar da cewa adreshin daidai ne kamin ka tura abua a ciki</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Waɗannan adiresoshin Bitcoin ne don karɓar kuɗi. Yi amfani da maɓallin 'Ƙirƙiri sabon adireshin karɓa' a cikin shafin karɓa don ƙirƙirar sababbin adireshi.
+zaka iya shiga ne kawai da adiresoshin 'na musamman' kawai.</translation>
+ </message>
+ </context>
+<context>
+ <name>QObject</name>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(sufficient to restore backups %n day(s) old)</source>
+ <extracomment>Explanatory text on the capability of the current prune target.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp; Fitarwa</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Fitar da bayanan da ke cikin shafin na yanzu zuwa fayil</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts
index 71d42a1345..d7346393b2 100644
--- a/src/qt/locale/bitcoin_he.ts
+++ b/src/qt/locale/bitcoin_he.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">לחיצה על הלחצן הימני בעכבר לעריכת הכתובת ×ו התווית</translation>
+ <translation type="unfinished">לחץ על הלחצן הימני בעכבר לעריכת הכתובת ×ו התווית</translation>
</message>
<message>
<source>Create a new address</source>
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation type="unfinished">העתקת ×ת הכתובת המסומנת ללוח</translation>
+ <translation type="unfinished">העתק ×ת הכתובת המסומנת ללוח</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -430,10 +430,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">שגי××” בנסיון ×œ×§×¨×•× ×ת %s! כל המפתחות נקר×ו נכונה, ×ך נתוני העסקה ×ו הכתובות יתכן שחסרו ×ו שגויי×.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">שגי××”: ×”××–× ×” לתקשורת × ×›×  סת נכשלה (×”×”××–× ×” מחזירה שגי××” %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">×מדן גובה עמלה נכשל. Fallbackfee  מנוטרל. יש להמתין מספר ×‘×œ×•×§×™× ×ו לשפעל ×ת -fallbackfee</translation>
</message>
@@ -590,10 +586,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">שגי×ת קרי××” ממסד הנתוני×. סוגר ×ת התהליך.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">שגי×ת שידרוג מסד ×”× ×ª×•× ×™× ×©×œ מצב השרשרת chainstate</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">שגי××”: שטח הדיסק קטן מדי עובר %s</translation>
</message>
@@ -670,10 +662,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">יש לציין פתחה ×¢× â€Ž-whitebind:†'%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">×œ× ×”×•×’×“×¨ פרוקסי. יש להשתמש ב־‎ -proxy=&lt;ip&gt; ×ו ב־‎ -proxy=&lt;ip:port&gt;.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">×ין מספיק מידע על הקובץ</translation>
</message>
@@ -802,10 +790,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">קטגורית ×¨×™×©×•× ×‘×œ×•×’ ש××™× ×” נמתמכת %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">שדרוג מ×גר נתוני UTXO </translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">הערת צד המשתמש (%s) כוללת ×ª×•×•×™× ×©××™× × ×‘×˜×•×—×™×.</translation>
</message>
@@ -1062,6 +1046,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">×ין ××¨× ×§×™× ×–×ž×™× ×™×</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">×©× ×”×רנק</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;חלון</translation>
</message>
@@ -1503,6 +1492,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Bitcoin</source>
<translation type="unfinished">ביטקוין</translation>
</message>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">לפחות %1 ג״ב של × ×ª×•× ×™× ×™×וחסנו בתיקייה זו, ×•×”× ×™×’×“×œ×• ×¢× ×”×–×ž×Ÿ.</translation>
@@ -1548,10 +1558,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">כיוון שזו ההפעלה הר×שונה של התכנית, ניתן לבחור היכן ×™×וחסן המידע של %1.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">בעת לחיצה על ×ישור, %1 יחל בהורדה ועיבוד מל××™× ×©×œ שרשרת ×”×ž×§×˜×¢×™× %4 (%2 ג״ב) החל מההעברות הר×שונות ב־%3 ×¢× ×”×”×©×§×” הר×שונית של %4.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">הגבלת ×חסון בלוקצ'יין ל</translation>
</message>
@@ -1848,10 +1854,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">השתמש בפרוקסי נפרד SOCKS&amp;5 להגעה ×œ×¢×ž×™×ª×™× ×“×¨×š שרותי השכבות של Tor :</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">×פשרויות שמוגדרות בדי×לוג ×”×–×” נדרסות ×¢"×™ שורת הפקודה ×ו קובץ הקונפיגורציה</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;×ישור</translation>
</message>
@@ -1869,14 +1871,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">×ישור ×יפוס ×”×פשרויות</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">נדרשת הפעלה מחדש של הלקוח כדי להפעיל ×ת השינויי×.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">הלקוח יכבה. להמשיך?</translation>
</message>
<message>
@@ -2903,10 +2908,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">עמלה מעל ×œ×¡×›×•× ×©×œ %1 נחשבת לעמלה גבוהה ב×ופן מוגז×.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">בקשת ×”×ª×©×œ×•× ×¤×’×”.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2986,14 +2987,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">הודעה:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">זוהי בקשת ×ª×©×œ×•× ×œ× ×ž×ומתת.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">זוהי בקשה מ×ומתת לתשלו×.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">יש לתת תווית לכתובת זו כדי להוסיף ×ותה לרשימת הכתובות בשימוש</translation>
</message>
@@ -3001,14 +2994,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">הודעה שצורפה לביטקוין: כתובת שת×וחסן בהעברה לצורך מעקב מצדך. לתשומת לבך: הודעה זו ×œ× ×ª×™×©×œ×— ברשת הביטקוין.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">×ª×©×œ×•× ×œ×˜×•×‘×ª:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">תזכורת:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3168,30 +3153,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">ישנה סתירה ×¢× ×¢×¡×§×” שעברה %1 ×ימותי×</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/×œ× ×ž×ומתי×, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">במ×גר הזיכרון</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">×œ× ×‘×ž×גר הזיכרון</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">ננטש</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/×œ× ×ž×ומתי×</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 ×ימותי×</translation>
</message>
<message>
@@ -3659,7 +3636,7 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation type="unfinished">שמירת ×”× ×ª×•× ×™× ×ž×”×œ×©×•× ×™×ª הנוכחית לקובץ</translation>
+ <translation type="unfinished">×™×¦×•× ×”× ×ª×•× ×™× ×‘×œ×©×•× ×™×ª הנוכחית לקובץ</translation>
</message>
<message>
<source>Backup Wallet</source>
diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts
index 1073d6b2f5..f02761a5ca 100644
--- a/src/qt/locale/bitcoin_hr.ts
+++ b/src/qt/locale/bitcoin_hr.ts
@@ -70,6 +70,12 @@
<translation type="unfinished">Ovo su vaše Bitcoin adrese za slanje novca. Uvijek provjerite iznos i adresu primatelja prije slanja novca.</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Ovo su vaše Bitcoin adrese za primanje sredstava. Koristite 'Kreiraj novu adresu za primanje' u tabu Primite kako biste kreirali nove adrese.
+Potpisivanje je moguće samo sa 'legacy' adresama. </translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">&amp;Kopirajte adresu</translation>
</message>
@@ -86,6 +92,11 @@
<translation type="unfinished">Izvezite listu adresa</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Datoteka podataka odvojenih zarezima (*.csv)</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">Došlo je do pogreške kod spremanja liste adresa na %1. Molimo pokušajte ponovno.</translation>
@@ -233,8 +244,37 @@
</message>
</context>
<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">Runaway iznimka</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">Dogodila se greška. %1 ne može sigurno nastaviti te će se zatvoriti.</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">Interna greška</translation>
+ </message>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">Dogodila se interna greÅ¡ka. %1 će pokuÅ¡ati sigurno nastaviti. Ovo je neoÄekivani bug koji se može prijaviti kao Å¡to je objaÅ¡njeno ispod.</translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Želite li resetirati postavke na poÄetne vrijednosti ili izaći bez promjena?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Dogodila se kobna greška. Provjerite je li datoteka za postavke otvorena za promjene ili pokušajte pokrenuti s -nosettings.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Greška: Zadana podatkovna mapa "%1" ne postoji.</translation>
</message>
@@ -247,6 +287,10 @@
<translation type="unfinished">Greška: %1</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 se nije joÅ¡ zatvorio na siguran naÄin.</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation type="unfinished">nepoznato</translation>
</message>
@@ -259,6 +303,14 @@
<translation type="unfinished">Unesite Bitcoin adresu (npr. %1)</translation>
</message>
<message>
+ <source>Unroutable</source>
+ <translation type="unfinished">Neusmjeriv</translation>
+ </message>
+ <message>
+ <source>Internal</source>
+ <translation type="unfinished">Interni</translation>
+ </message>
+ <message>
<source>Inbound</source>
<extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
<translation type="unfinished">Dolazni</translation>
@@ -269,6 +321,31 @@
<translation type="unfinished">Izlazni</translation>
</message>
<message>
+ <source>Full Relay</source>
+ <extracomment>Peer connection type that relays all network information.</extracomment>
+ <translation type="unfinished">Potpuni prijenos</translation>
+ </message>
+ <message>
+ <source>Block Relay</source>
+ <extracomment>Peer connection type that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">Blok prijenos</translation>
+ </message>
+ <message>
+ <source>Manual</source>
+ <extracomment>Peer connection type established manually through one of several methods.</extracomment>
+ <translation type="unfinished">PriruÄnik</translation>
+ </message>
+ <message>
+ <source>Feeler</source>
+ <extracomment>Short-lived peer connection type that tests the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">IspipavaÄ</translation>
+ </message>
+ <message>
+ <source>Address Fetch</source>
+ <extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
+ <translation type="unfinished">Dohvaćanje adrese</translation>
+ </message>
+ <message>
<source>None</source>
<translation type="unfinished">Ništa</translation>
</message>
@@ -328,18 +405,38 @@
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Datoteka postavke se ne može proÄitati</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Datoteka postavke se ne može mijenjati</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">Ekipa %s</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation type="unfinished">%s korumpirano. PokuÅ¡ajte koristiti bitcoin-wallet alat za novÄanike kako biste ga spasili ili pokrenuti sigurnosnu kopiju.</translation>
+ </message>
+ <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation type="unfinished">-maxtxfee je postavljen preveliko. Naknade ove veliÄine će biti plaćene na individualnoj transakciji.</translation>
</message>
<message>
+ <source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
+ <translation type="unfinished">Nije moguće unazaditi novÄanik s verzije %i na verziju %i. Verzija novÄanika nepromijenjena.</translation>
+ </message>
+ <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation type="unfinished">Program ne može pristupiti podatkovnoj mapi %s. %s je vjerojatno već pokrenut.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Nije moguće unaprijediti podijeljeni novÄanik bez HD-a s verzije %i na verziju %i bez unaprijeÄ‘enja na potporu pred-podjelnog bazena kljuÄeva. Molimo koristite verziju %i ili neku drugu.</translation>
+ </message>
+ <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation type="unfinished">Distribuirano pod MIT licencom softvera. Vidite pripadajuću datoteku %s ili %s.</translation>
</message>
@@ -348,18 +445,58 @@
<translation type="unfinished">GreÅ¡ka kod iÅ¡Äitanja %s! Svi kljuÄevi su ispravno uÄitani, ali transakcijski podaci ili zapisi u adresaru mogu biti nepotpuni ili netoÄni.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Greška: Neuspješno slušanje dolažećih veza (listen je izbacio grešku %s)</translation>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">GreÅ¡ka u Äitanju %s! Transakcijski podaci nedostaju ili su netoÄni. Ponovno skeniranje novÄanika.</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
+ <translation type="unfinished">GreÅ¡ka: Format dumpfile zapisa je netoÄan. Dobiven "%s" oÄekivani "format".</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile identifier record is incorrect. Got "%s", expected "%s".</source>
+ <translation type="unfinished">GreÅ¡ka: Identifikator dumpfile zapisa je netoÄan. Dobiven "%s", oÄekivan "%s".</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
+ <translation type="unfinished">Greška: Dumpfile verzija nije podržana. Ova bitcoin-wallet  verzija podržava samo dumpfile verziju 1. Dobiven dumpfile s verzijom %s</translation>
+ </message>
+ <message>
+ <source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
+ <translation type="unfinished">GreÅ¡ka: Legacy novÄanici podržavaju samo "legacy", "p2sh-segwit", i "bech32" tipove adresa</translation>
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">NeuspjeÅ¡no procjenjivanje naknada. Fallbackfee je iskljuÄena. PriÄekajte nekoliko blokova ili ukljuÄite -fallbackfee.</translation>
</message>
<message>
+ <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">Datoteka %s već postoji. Ako ste sigurni da ovo želite, prvo ju maknite, </translation>
+ </message>
+ <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation type="unfinished">Neispravan iznos za -maxtxfee=&lt;amount&gt;: '%s' (mora biti barem minimalnu naknadu za proslijeđivanje od %s kako se ne bi zapela transakcija)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Nevažeći ili korumpirani peers.dat (%s). Ako mislite da je ovo bug, molimo prijavite %s. Kao alternativno rješenje, možete maknuti datoteku (%s) (preimenuj, makni ili obriši) kako bi se kreirala nova na idućem pokretanju.</translation>
+ </message>
+ <message>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation type="unfinished">Pruženo je više od jedne onion bind adrese. Koristim %s za automatski stvorenu Tor onion uslugu.</translation>
+ </message>
+ <message>
+ <source>No dump file provided. To use createfromdump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">Dump datoteka nije automatski dostupna. Kako biste koristili createfromdump, -dumpfile=&lt;filename&gt; mora biti osiguran. </translation>
+ </message>
+ <message>
+ <source>No dump file provided. To use dump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">Dump datoteka nije automatski dostupna. Kako biste koristili dump, -dumpfile=&lt;filename&gt; mora biti osiguran. </translation>
+ </message>
+ <message>
+ <source>No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
+ <translation type="unfinished">Format datoteke novÄanika nije dostupan. Kako biste koristili reatefromdump, -format=&lt;format&gt; mora biti osiguran.</translation>
+ </message>
+ <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation type="unfinished">Molimo provjerite jesu li datum i vrijeme na vaÅ¡em raÄunalu toÄni. Ako je vaÅ¡ sat krivo namjeÅ¡ten, %s neće raditi ispravno.</translation>
</message>
@@ -376,18 +513,34 @@
<translation type="unfinished">Obrezivanje: zadnja sinkronizacija novÄanika ide dalje od obrezivanih podataka. Morate koristiti -reindex (ponovo preuzeti cijeli lanac blokova u sluÄaju obrezivanog Ävora)</translation>
</message>
<message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation type="unfinished">SQLiteDatabase: Nepoznata sqlite shema novÄanika verzija %d. Podržana je samo verzija %d.</translation>
+ </message>
+ <message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation type="unfinished">Baza blokova sadrži blok koji je naizgled iz budućnosti. Može to biti posljedica krivo namjeÅ¡tenog datuma i vremena na vaÅ¡em raÄunalu. Obnovite bazu blokova samo ako ste sigurni da su toÄni datum i vrijeme na vaÅ¡em raÄunalu.</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">Index bloka db sadrži legacy 'txindex'. Kako biste oÄistili zauzeti prostor na disku, pokrenite puni -reindex ili ignorirajte ovu greÅ¡ku. Ova greÅ¡ka neće biti ponovno prikazana.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">Iznos transakcije je premalen za poslati nakon naknade</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Ova greÅ¡ka bi se mogla dogoditi kada se ovaj novÄanik ne ugasi pravilno i ako je posljednji put bio podignut koristeći noviju verziju Berkeley DB. Ako je tako, molimo koristite softver kojim je novÄanik podignut zadnji put.</translation>
+ </message>
+ <message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
<translation type="unfinished">Ovo je eksperimentalna verzija za testiranje - koristite je na vlastitu odgovornost - ne koristite je za rudarenje ili trgovaÄke primjene</translation>
</message>
<message>
+ <source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
+ <translation type="unfinished">Ovo je najveća transakcijska naknada koju plaćate (uz normalnu naknadu) kako biste prioritizirali izbjegavanje djelomiÄne potroÅ¡nje nad uobiÄajenom selekcijom sredstava.</translation>
+ </message>
+ <message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
<translation type="unfinished">Ovo je transakcijska naknada koju možete odbaciti ako je ostatak manji od "prašine" (sićušnih iznosa) po ovoj stopi</translation>
</message>
@@ -404,6 +557,14 @@
<translation type="unfinished">Ne mogu se ponovo odigrati blokovi. Morat ćete ponovo složiti bazu koristeći -reindex-chainstate.</translation>
</message>
<message>
+ <source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
+ <translation type="unfinished">Nepoznati formant novÄanika "%s" pružen. Molimo dostavite "bdb" ili "sqlite".</translation>
+ </message>
+ <message>
+ <source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
+ <translation type="unfinished">Upozorenje: Dumpfile format novÄanika "%s" se ne poklapa sa formatom komandne linije "%s".</translation>
+ </message>
+ <message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
<translation type="unfinished">Upozorenje: Privatni kljuÄevi pronaÄ‘eni u novÄaniku {%s} s iskljuÄenim privatnim kljuÄevima</translation>
</message>
@@ -412,6 +573,10 @@
<translation type="unfinished">Upozorenje: Izgleda da se ne slažemo u potpunosti s naÅ¡im klijentima! Možda ćete se vi ili ostali Ävorovi morati ažurirati.</translation>
</message>
<message>
+ <source>Witness data for blocks after height %d requires validation. Please restart with -reindex.</source>
+ <translation type="unfinished">Podaci svjedoka za blokove poslije visine %d zahtijevaju validaciju. Molimo restartirajte sa -reindex.</translation>
+ </message>
+ <message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
<translation type="unfinished">Morat ćete ponovno složiti bazu koristeći -reindex kako biste se vratili na neobrezivan naÄin (unpruned mode). Ovo će ponovno preuzeti cijeli lanac blokova.</translation>
</message>
@@ -424,14 +589,46 @@
<translation type="unfinished">-maxmempool mora biti barem %d MB</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation type="unfinished">Dogodila se kobna greška, vidi detalje u debug.log.</translation>
+ </message>
+ <message>
<source>Cannot resolve -%s address: '%s'</source>
<translation type="unfinished">Ne može se razriješiti adresa -%s: '%s'</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">Nije moguće postaviti -forcednsseed na true kada je postavka za -dnsseed false.</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation type="unfinished">Nije moguće postaviti -peerblockfilters bez -blockfilterindex.</translation>
+ </message>
+ <message>
<source>Cannot write to data directory '%s'; check permissions.</source>
<translation type="unfinished">Nije moguće pisati u podatkovnu mapu '%s'; provjerite dozvole.</translation>
</message>
<message>
+ <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">UnaprijeÄ‘enje -txindex koje za zapoÄela prijaÅ¡nja verzija nije moguće zavrÅ¡iti. Ponovno pokrenite s prethodnom verzijom ili pokrenite potpuni -reindex.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s zahtjev za slušanje na portu %u. Ovaj port se smatra "lošim" i time nije vjerojatno da će se drugi Bitcoin Core peerovi spojiti na njega. Pogledajte doc/p2p-bad-ports.md za detalje i cijeli popis.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Nije moguće ponuditi specifiÄne veze i istovremeno dati addrman da traži izlazne veze.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">PogreÅ¡ka pri uÄitavanju %s: Vanjski potpisni novÄanik se uÄitava bez kompajlirane potpore vanjskog potpisnika</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Preimenovanje nevažeće peers.dat datoteke neuspješno. Molimo premjestite ili obrišite datoteku i pokušajte ponovno.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Konfiguriranje postavki za %s primijenjeno je samo na %s mreži u odjeljku [%s].</translation>
</message>
@@ -448,6 +645,10 @@
<translation type="unfinished">Nije moguće proÄitati asmap datoteku %s</translation>
</message>
<message>
+ <source>Disk space is too low!</source>
+ <translation type="unfinished">Nema dovoljno prostora na disku!</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation type="unfinished">Želite li sada obnoviti bazu blokova?</translation>
</message>
@@ -456,6 +657,14 @@
<translation type="unfinished">UÄitavanje gotovo</translation>
</message>
<message>
+ <source>Dump file %s does not exist.</source>
+ <translation type="unfinished">Dump datoteka %s ne postoji.</translation>
+ </message>
+ <message>
+ <source>Error creating %s</source>
+ <translation type="unfinished">Greška pri stvaranju %s</translation>
+ </message>
+ <message>
<source>Error initializing block database</source>
<translation type="unfinished">Greška kod inicijaliziranja baze blokova</translation>
</message>
@@ -492,14 +701,50 @@
<translation type="unfinished">GreÅ¡ka kod iÅ¡Äitanja baze. Zatvara se klijent.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Greška kod ažuriranja baze stanja lanca</translation>
+ <source>Error reading next record from wallet database</source>
+ <translation type="unfinished">GreÅ¡ka pri oÄitavanju idućeg zapisa iz baza podataka novÄanika</translation>
+ </message>
+ <message>
+ <source>Error: Couldn't create cursor into database</source>
+ <translation type="unfinished">Greška: Nije moguće kreirati cursor u batu podataka</translation>
</message>
<message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Pogreška: Malo diskovnog prostora za %s</translation>
</message>
<message>
+ <source>Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
+ <translation type="unfinished">GreÅ¡ka: Dumpfile checksum se ne poklapa. IzraÄunao %s, oÄekivano %s</translation>
+ </message>
+ <message>
+ <source>Error: Got key that was not hex: %s</source>
+ <translation type="unfinished">GreÅ¡ka: Dobiven kljuÄ koji nije hex: %s</translation>
+ </message>
+ <message>
+ <source>Error: Got value that was not hex: %s</source>
+ <translation type="unfinished">Greška: Dobivena vrijednost koja nije hex: %s</translation>
+ </message>
+ <message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation type="unfinished">GreÅ¡ka: Ispraznio se bazen kljuÄeva, molimo prvo pozovite keypoolrefill</translation>
+ </message>
+ <message>
+ <source>Error: Missing checksum</source>
+ <translation type="unfinished">Greška: Nedostaje checksum</translation>
+ </message>
+ <message>
+ <source>Error: No %s addresses available.</source>
+ <translation type="unfinished">Greška: Nema %s adresa raspoloživo.</translation>
+ </message>
+ <message>
+ <source>Error: Unable to parse version %u as a uint32_t</source>
+ <translation type="unfinished">Greška: Nije moguće parsirati verziju %u kao uint32_t</translation>
+ </message>
+ <message>
+ <source>Error: Unable to write record to new wallet</source>
+ <translation type="unfinished">GreÅ¡ka: Nije moguće unijeti zapis u novi novÄanik</translation>
+ </message>
+ <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">Neuspješno slušanje na svim portovima. Koristite -listen=0 ako to želite.</translation>
</message>
@@ -508,6 +753,22 @@
<translation type="unfinished">NeuspjeÅ¡no ponovo skeniranje novÄanika tijekom inicijalizacije</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation type="unfinished">Verifikacija baze podataka neuspješna</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation type="unfinished">Naknada (%s) je niža od postavke minimalne visine naknade (%s)</translation>
+ </message>
+ <message>
+ <source>Ignoring duplicate -wallet %s.</source>
+ <translation type="unfinished">Zanemarujem duplicirani -wallet %s.</translation>
+ </message>
+ <message>
+ <source>Importing…</source>
+ <translation type="unfinished">Uvozim...</translation>
+ </message>
+ <message>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
<translation type="unfinished">Neispravan ili nepostojeći blok geneze. Možda je kriva podatkovna mapa za mrežu?</translation>
</message>
@@ -516,10 +777,18 @@
<translation type="unfinished">Brzinska provjera inicijalizacije neuspješna. %s se zatvara.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Input nije pronađen ili je već potrošen</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">Nedovoljna sredstva</translation>
</message>
<message>
+ <source>Invalid -i2psam address or hostname: '%s'</source>
+ <translation type="unfinished">Neispravna -i2psam adresa ili ime raÄunala: '%s'</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation type="unfinished">Neispravna -onion adresa ili ime raÄunala: '%s'</translation>
</message>
@@ -552,10 +821,38 @@
<translation type="unfinished">Neispravna mrežna maska zadana u -whitelist: '%s'</translation>
</message>
<message>
+ <source>Loading P2P addresses…</source>
+ <translation type="unfinished">Pokreće se popis P2P adresa...</translation>
+ </message>
+ <message>
+ <source>Loading banlist…</source>
+ <translation type="unfinished">Pokreće se popis zabrana...</translation>
+ </message>
+ <message>
+ <source>Loading block index…</source>
+ <translation type="unfinished">UÄitavanje indeksa blokova...</translation>
+ </message>
+ <message>
+ <source>Loading wallet…</source>
+ <translation type="unfinished">UÄitavanje novÄanika...</translation>
+ </message>
+ <message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Iznos nedostaje</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">Nedostaju podaci za procjenu veliÄine transakcije</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Treba zadati port pomoću -whitebind: '%s'</translation>
</message>
<message>
+ <source>No addresses available</source>
+ <translation type="unfinished">Nema dostupnih adresa</translation>
+ </message>
+ <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Nema dovoljno dostupnih datoteÄnih opisivaÄa.</translation>
</message>
@@ -568,10 +865,38 @@
<translation type="unfinished">NaÄin obreživanja (pruning) nekompatibilan je s parametrom -txindex.</translation>
</message>
<message>
+ <source>Pruning blockstore…</source>
+ <translation type="unfinished">Pruning blockstore-a...</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation type="unfinished">Smanjuje se -maxconnections sa %d na %d zbog sustavnih ograniÄenja.</translation>
</message>
<message>
+ <source>Replaying blocks…</source>
+ <translation type="unfinished">Premotavam blokove...</translation>
+ </message>
+ <message>
+ <source>Rescanning…</source>
+ <translation type="unfinished">Ponovno pretraživanje...</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation type="unfinished">SQLiteDatabase: Neuspješno izvršenje izjave za verifikaciju baze podataka: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation type="unfinished">SQLiteDatabase: Neuspješno pripremanje izjave za verifikaciju baze: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation type="unfinished">SQLiteDatabase: NeuspjeÅ¡no Äitanje greÅ¡ke verifikacije baze podataka %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation type="unfinished">SQLiteDatabase: NeoÄekivani id aplikacije. OÄekvano %u, pronaÄ‘eno %u</translation>
+ </message>
+ <message>
<source>Section [%s] is not recognized.</source>
<translation type="unfinished">Odjeljak [%s] nije prepoznat.</translation>
</message>
@@ -596,10 +921,18 @@
<translation type="unfinished">Zadana mapa blokova "%s" ne postoji.</translation>
</message>
<message>
+ <source>Starting network threads…</source>
+ <translation type="unfinished">Pokreću se mrežne niti...</translation>
+ </message>
+ <message>
<source>The source code is available from %s.</source>
<translation type="unfinished">Izvorni kod je dostupan na %s.</translation>
</message>
<message>
+ <source>The specified config file %s does not exist</source>
+ <translation type="unfinished">Navedena konfiguracijska datoteka %s ne postoji</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to pay the fee</source>
<translation type="unfinished">Transakcijiski iznos je premalen da plati naknadu</translation>
</message>
@@ -628,6 +961,10 @@
<translation type="unfinished">Iznosi transakcije ne smiju biti negativni</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Indeks change outputa transakcije je izvan dometa</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">Transakcija ima prevelik lanac memorijskog bazena</translation>
</message>
@@ -636,6 +973,10 @@
<translation type="unfinished">Transakcija mora imati barem jednog primatelja</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Transakciji je potrebna change adresa, ali ju ne možemo generirati.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Transakcija prevelika</translation>
</message>
@@ -660,6 +1001,14 @@
<translation type="unfinished">Ne mogu se generirati kljuÄevi</translation>
</message>
<message>
+ <source>Unable to open %s for writing</source>
+ <translation type="unfinished">Ne mogu otvoriti %s za upisivanje</translation>
+ </message>
+ <message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">Nije moguće parsirati -maxuploadtarget: '%s'</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">Ne može se pokrenuti HTTP server. Vidite debug.log za više detalja.</translation>
</message>
@@ -680,18 +1029,26 @@
<translation type="unfinished">Nepoznata mreža zadana kod -onlynet: '%s'</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">Nepodržana kategorija zapisa %s=%s.</translation>
+ <source>Unknown new rules activated (versionbit %i)</source>
+ <translation type="unfinished"> Nepoznata nova pravila aktivirana (versionbit %i)</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Ažurira se UTXO baza</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Nepodržana kategorija zapisa %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Komentar pod "KorisniÄki agent" (%s) sadrži nesigurne znakove.</translation>
</message>
<message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">Provjervanje blokova...</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)…</source>
+ <translation type="unfinished">Provjeravanje novÄanika...</translation>
+ </message>
+ <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation type="unfinished">NovÄanik je trebao prepravak: ponovo pokrenite %s</translation>
</message>
@@ -740,13 +1097,17 @@
</message>
<message>
<source>Modify configuration options for %1</source>
- <translation type="unfinished">Promijenite postavke za %1</translation>
+ <translation type="unfinished">Promijeni konfiguraciju opcija za %1</translation>
</message>
<message>
<source>Create a new wallet</source>
<translation type="unfinished">Stvorite novi novÄanik</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Minimiziraj</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">NovÄanik:</translation>
</message>
@@ -761,7 +1122,7 @@
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation type="unfinished">Pošaljite novac na Bitcoin adresu</translation>
+ <translation type="unfinished">Pošaljite sredstva na Bitcoin adresu</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -777,21 +1138,65 @@
</message>
<message>
<source>&amp;Receive</source>
- <translation type="unfinished">Pri&amp;mite</translation>
+ <translation type="unfinished">&amp;Primite</translation>
+ </message>
+ <message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;Opcije</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;Å ifriraj novÄanik</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
<translation type="unfinished">Å ifrirajte privatne kljuÄeve u novÄaniku</translation>
</message>
<message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;Kreiraj sigurnosnu kopiju novÄanika</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;Promijeni lozinku</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">Potpiši &amp;poruku</translation>
+ </message>
+ <message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
<translation type="unfinished">Poruku potpišemo s Bitcoin adresom, kako bi dokazali vlasništvo nad tom adresom</translation>
</message>
<message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;Potvrdi poruku</translation>
+ </message>
+ <message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
<translation type="unfinished">Provjerite poruku da je potpisana s navedenom Bitcoin adresom</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">&amp;UÄitaj PSBT iz datoteke...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">Otvori &amp;URI adresu...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">Zatvori novÄanik...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">Kreiraj novÄanik...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">Zatvori sve novÄanike...</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation type="unfinished">&amp;Datoteka</translation>
</message>
@@ -808,6 +1213,30 @@
<translation type="unfinished">Traka kartica</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Sinkronizacija zaglavlja bloka (%1%)...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Sinkronizacija s mrežom...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Indeksiranje blokova na disku...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Obrađivanje blokova na disku...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Reindeksiranje blokova na disku...</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">Povezivanje sa peer-ovima...</translation>
+ </message>
+ <message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished">Zatražite uplatu (stvara QR kod i bitcoin: URI adresu)</translation>
</message>
@@ -836,6 +1265,10 @@
<translation type="unfinished">%1 iza</translation>
</message>
<message>
+ <source>Catching up…</source>
+ <translation type="unfinished">Ažuriranje...</translation>
+ </message>
+ <message>
<source>Last received block was generated %1 ago.</source>
<translation type="unfinished">Zadnji primljeni blok je bio ustvaren prije %1.</translation>
</message>
@@ -864,6 +1297,10 @@
<translation type="unfinished">UÄitaj djelomiÄno potpisanu bitcoin transakciju</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">UÄitaj PSBT iz &amp;meÄ‘uspremnika...</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">UÄitaj djelomiÄno potpisanu bitcoin transakciju iz meÄ‘uspremnika</translation>
</message>
@@ -908,6 +1345,14 @@
<translation type="unfinished">Prikažite pomoć programa %1 kako biste ispisali moguće opcije preko terminala</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">&amp;Sakrij vrijednosti</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">Sakrij vrijednost u tabu Pregled </translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">uobiÄajeni novÄanik</translation>
</message>
@@ -916,6 +1361,16 @@
<translation type="unfinished">Nema dostupnih novÄanika</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Podaci novÄanika</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Ime novÄanika</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Prozor</translation>
</message>
@@ -931,6 +1386,14 @@
<source>%1 client</source>
<translation type="unfinished">%1 klijent</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Sakrij</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">&amp;Pokaži</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -941,6 +1404,26 @@
</translation>
</message>
<message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Klikni za više radnji.</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">Pokaži Peers tab </translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">Onemogući mrežnu aktivnost</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">Omogući mrežnu aktivnost</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Greška: %1</translation>
</message>
@@ -963,7 +1446,8 @@
<message>
<source>Wallet: %1
</source>
- <translation type="unfinished">NovÄanik: %1</translation>
+ <translation type="unfinished">NovÄanik: %1
+</translation>
</message>
<message>
<source>Type: %1
@@ -1011,7 +1495,11 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation type="unfinished">NovÄanik je &lt;b&gt;Å¡ifriran&lt;/b&gt; i trenutno &lt;b&gt;zakljuÄan&lt;/b&gt;</translation>
</message>
- </context>
+ <message>
+ <source>Original message:</source>
+ <translation type="unfinished">Originalna poruka:</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
<message>
@@ -1094,6 +1582,30 @@
<translation type="unfinished">Kopirajte iznos</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopiraj adresu</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiraj &amp;oznaku</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopiraj &amp;iznos</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Kopiraj &amp;ID transakcije i output index</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">&amp;ZakljuÄaj nepotroÅ¡en input</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">&amp;OtkljuÄaj nepotroÅ¡en input</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Kopirajte iznos</translation>
</message>
@@ -1158,6 +1670,11 @@
<translation type="unfinished">Stvorite novÄanik</translation>
</message>
<message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">Kreiranje novÄanika &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
<source>Create wallet failed</source>
<translation type="unfinished">NeuspjeÅ¡no stvaranje novÄanika</translation>
</message>
@@ -1165,8 +1682,25 @@
<source>Create wallet warning</source>
<translation type="unfinished">Upozorenje kod stvaranja novÄanika</translation>
</message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Nije moguće izlistati potpisnike</translation>
+ </message>
</context>
<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">UÄitaj novÄanike</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">UÄitavanje novÄanika...</translation>
+ </message>
+</context>
+<context>
<name>OpenWalletActivity</name>
<message>
<source>Open wallet failed</source>
@@ -1185,7 +1719,12 @@
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">Otvorite novÄanik</translation>
</message>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">Otvaranje novÄanika &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
@@ -1198,13 +1737,17 @@
</message>
<message>
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
- <translation type="unfinished">Držanje novÄanik zatvorenim predugo može rezultirati ponovnom sinkronizacijom cijelog lanca ako je obrezivanje ukljuÄeno.</translation>
+ <translation type="unfinished">Držanje novÄanik zatvorenim predugo može rezultirati ponovnom sinkronizacijom cijelog lanca ako je ukljuÄen pruning (odbacivanje dijela podataka).</translation>
</message>
<message>
<source>Close all wallets</source>
<translation type="unfinished">Zatvori sve novÄanike</translation>
</message>
- </context>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation type="unfinished">Jeste li sigurni da želite zatvoriti sve novÄanike?</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
<message>
@@ -1228,6 +1771,10 @@
<translation type="unfinished">Å ifrirajte novÄanik</translation>
</message>
<message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">Napredne opcije</translation>
+ </message>
+ <message>
<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">IskljuÄite privatne kljuÄeve za ovaj novÄanik. NovÄanici gdje su privatni kljuÄevi iskljuÄeni neće sadržati privatne kljuÄeve te ne mogu imati HD sjeme ili uvezene privatne kljuÄeve. Ova postavka je idealna za novÄanike koje su iskljuÄivo za promatranje.</translation>
</message>
@@ -1244,10 +1791,35 @@
<translation type="unfinished">Stvorite prazni novÄanik</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation type="unfinished">Koristi deskriptore za upravljanje scriptPubKey-a</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">Deskriptor novÄanik</translation>
+ </message>
+ <message>
+ <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
+ <translation type="unfinished">Koristi vanjski potpisni ureÄ‘aj kao Å¡to je hardverski novÄanik. Prije koriÅ¡tenja konfiguriraj vanjski potpisni skript u postavkama novÄanika.</translation>
+ </message>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">Vanjski potpisnik</translation>
+ </message>
+ <message>
<source>Create</source>
<translation type="unfinished">Stvorite</translation>
</message>
- </context>
+ <message>
+ <source>Compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished">Kompajlirano bez sqlite mogućnosti (potrebno za deskriptor novÄanike)</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Kompajlirano bez mogućnosti vanjskog potpisivanje (potrebno za vanjsko potpisivanje)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -1307,7 +1879,7 @@
<name>FreespaceChecker</name>
<message>
<source>A new data directory will be created.</source>
- <translation type="unfinished">Bit će stvorena nova podatkovna mapa.</translation>
+ <translation type="unfinished">Biti će stvorena nova podatkovna mapa.</translation>
</message>
<message>
<source>name</source>
@@ -1328,6 +1900,30 @@
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Bit će spremljeno barem %1 GB podataka u ovoj mapi te će se povećati tijekom vremena.</translation>
@@ -1374,8 +1970,8 @@
<translation type="unfinished">Kako je ovo prvi put da je ova aplikacija pokrenuta, možete izabrati gdje će %1 spremati svoje podatke.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Kada kliknete OK, %1 poÄet će preuzimati i procesirati cijeli lanac blokova (%2GB) poÄevÅ¡i s najranijim transakcijama u %3 kad je %4 prvi put pokrenut.</translation>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">OgraniÄi pohranu u blockchain na:</translation>
</message>
<message>
<source>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>
@@ -1387,7 +1983,7 @@
</message>
<message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation type="unfinished">Ako odluÄite ograniÄiti spremanje lanca blokova pomoću pruninga (obrezivanja), treba preuzeti i procesirati povijesne podatke. Bit će obrisani naknadno kako bi se smanjila koliÄina zauzetog prostora na disku.</translation>
+ <translation type="unfinished">Ako odluÄite ograniÄiti spremanje lanca blokova pomoću pruninga, treba preuzeti i procesirati povijesne podatke. Bit će obrisani naknadno kako bi se smanjila koliÄina zauzetog prostora na disku.</translation>
</message>
<message>
<source>Use the default data directory</source>
@@ -1416,6 +2012,10 @@
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1 do zatvaranja...</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation type="unfinished">Ne ugasite raÄunalo dok ovaj prozor ne nestane.</translation>
</message>
@@ -1439,6 +2039,14 @@
<translation type="unfinished">Broj preostalih blokova</translation>
</message>
<message>
+ <source>Unknown…</source>
+ <translation type="unfinished">Nepoznato...</translation>
+ </message>
+ <message>
+ <source>calculating…</source>
+ <translation type="unfinished">raÄunam...</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation type="unfinished">Posljednje vrijeme bloka</translation>
</message>
@@ -1458,6 +2066,10 @@
<source>Hide</source>
<translation type="unfinished">Sakrijte</translation>
</message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Nepoznato. Sinkroniziranje zaglavlja blokova (%1, %2%)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1475,7 +2087,7 @@
<name>OptionsDialog</name>
<message>
<source>Options</source>
- <translation type="unfinished">Postavke</translation>
+ <translation type="unfinished">Opcije</translation>
</message>
<message>
<source>&amp;Main</source>
@@ -1490,6 +2102,10 @@
<translation type="unfinished">&amp;Pokrenite %1 kod prijave u sustav</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Omogućavanje pruninga smanjuje prostor na disku potreban za pohranu transakcija. Svi blokovi su još uvijek potpuno potvrđeni. Poništavanje ove postavke uzrokuje ponovno skidanje cijelog blockchaina.</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation type="unfinished">VeliÄina predmemorije baze podataka</translation>
</message>
@@ -1519,11 +2135,11 @@
</message>
<message>
<source>Reset all client options to default.</source>
- <translation type="unfinished">Nastavi sve postavke programa na poÄetne vrijednosti.</translation>
+ <translation type="unfinished">Resetiraj sve opcije programa na poÄetne vrijednosti.</translation>
</message>
<message>
<source>&amp;Reset Options</source>
- <translation type="unfinished">Po&amp;nastavi postavke</translation>
+ <translation type="unfinished">&amp;Resetiraj opcije</translation>
</message>
<message>
<source>&amp;Network</source>
@@ -1538,14 +2154,44 @@
<translation type="unfinished">Vraćanje na prijašnje stanje zahtijeva ponovo preuzimanje cijelog lanca blokova.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">Maksimalna veliÄina cachea baza podataka. Veći cache može doprinijeti bržoj sinkronizaciji, nakon koje je korisnost manje izražena za većinu sluÄajeva. Smanjenje cache veliÄine će smanjiti koriÅ¡tenje memorije. NekoriÅ¡tena mempool memorija se dijeli za ovaj cache. </translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Postavi broj skript verifikacijskih niti. Negativne vrijednosti odgovaraju broju jezgri koje trebate ostaviti slobodnima za sustav.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = automatski odredite, &lt;0 = ostavite slobodno upravo toliko jezgri)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Ovo omogućava vama ili vanjskom alatu komunikaciju s Ävorom kroz command-line i JSON-RPC komande.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">UkljuÄi &amp;RPC server</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">&amp;NovÄanik</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Za postavljanje oduzimanja naknade od iznosa kao zadano ili ne.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Oduzmi &amp;naknadu od iznosa kao zadano</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">StruÄne postavke</translation>
</message>
@@ -1562,6 +2208,28 @@
<translation type="unfinished">&amp;Trošenje nepotvrđenih vraćenih iznosa</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">UkljuÄi &amp;PBST opcije za upravljanje</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Za prikazivanje PSBT opcija za upravaljanje. </translation>
+ </message>
+ <message>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">Vanjski potpisnik (npr. hardverski novÄanik)</translation>
+ </message>
+ <message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">&amp;Put za vanjsku skriptu potpisnika</translation>
+ </message>
+ <message>
+ <source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
+ <translation type="unfinished">Cijeli put do Bitcoin Core kompatibilnog skripta (npr. C:\Downloads\hwi.exe ili /Users/you/Downloads/hwi.py). Upozerenje: malware može ukrasti vaša sredstva!</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">Automatski otvori port Bitcoin klijenta na ruteru. To radi samo ako ruter podržava UPnP i ako je omogućen.</translation>
</message>
@@ -1570,6 +2238,14 @@
<translation type="unfinished">Mapiraj port koristeći &amp;UPnP</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Automatski otvori port Bitcoin klijenta na ruteru. Ovo radi samo ako ruter podržava UPnP i ako je omogućen. Vanjski port može biti nasumiÄan.</translation>
+ </message>
+ <message>
+ <source>Map port using NA&amp;T-PMP</source>
+ <translation type="unfinished">Mapiraj port koristeći &amp;UPnP</translation>
+ </message>
+ <message>
<source>Accept connections from outside.</source>
<translation type="unfinished">Prihvatite veze izvana.</translation>
</message>
@@ -1614,6 +2290,14 @@
<translation type="unfinished">&amp;Prozor</translation>
</message>
<message>
+ <source>Show the icon in the system tray.</source>
+ <translation type="unfinished">Pokaži ikonu sa sustavne trake.</translation>
+ </message>
+ <message>
+ <source>&amp;Show tray icon</source>
+ <translation type="unfinished">&amp;Pokaži ikonu</translation>
+ </message>
+ <message>
<source>Show only a tray icon after minimizing the window.</source>
<translation type="unfinished">Prikaži samo ikonu u sistemskoj traci nakon minimiziranja prozora</translation>
</message>
@@ -1646,12 +2330,36 @@
<translation type="unfinished">Izaberite željeni najmanji dio bitcoina koji će biti prikazan u suÄelju i koji će se koristiti za plaćanje.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Vanjski URL-ovi transakcije (npr. preglednik blokova) koji se javljaju u kartici transakcija kao elementi kontekstnog izbornika. %s u URL-u zamijenjen je hashom transakcije. Višestruki URL-ovi su odvojeni vertikalnom crtom |.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;Vanjski URL-ovi transakcije</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Ovisi želite li prikazati mogućnosti kontroliranja inputa ili ne.</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Opcije postavljene u ovom dijalogu nadglašene su naredbenom linijom ili konfiguracijskom datotekom:</translation>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation type="unfinished">Spojite se na Bitcoin mrežu kroz zaseban SOCKS5 proxy za povezivanje na Tor onion usluge.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation type="unfinished">Koristite zaseban SOCKS&amp;5 proxy kako biste dohvatili klijente preko Tora:</translation>
+ </message>
+ <message>
+ <source>Monospaced font in the Overview tab:</source>
+ <translation type="unfinished">Font fiksne Å¡irine u tabu Pregled:</translation>
+ </message>
+ <message>
+ <source>embedded "%1"</source>
+ <translation type="unfinished">ugrađen "%1"</translation>
+ </message>
+ <message>
+ <source>closest matching "%1"</source>
+ <translation type="unfinished">najbliže poklapanje "%1"</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -1662,6 +2370,11 @@
<translation type="unfinished">&amp;Odustani</translation>
</message>
<message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Kompajlirano bez mogućnosti vanjskog potpisivanje (potrebno za vanjsko potpisivanje)</translation>
+ </message>
+ <message>
<source>default</source>
<translation type="unfinished">standardne vrijednosti</translation>
</message>
@@ -1671,20 +2384,23 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Potvrdite resetiranje opcija</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Potrebno je ponovno pokretanje klijenta kako bi se promjene aktivirale.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Zatvorit će se klijent. Želite li nastaviti?</translation>
</message>
<message>
<source>Configuration options</source>
<extracomment>Window title text of pop-up box that allows opening up of configuration file.</extracomment>
- <translation type="unfinished">Konfiguracijske postavke</translation>
+ <translation type="unfinished">Konfiguracijske opcije</translation>
</message>
<message>
<source>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>
@@ -1692,6 +2408,10 @@
<translation type="unfinished">Ova konfiguracijska datoteka je koriÅ¡tena za specificiranje napredne korisniÄke opcije koje će poniÅ¡titi postavke GUI-a. TakoÄ‘er će bilo koje opcije navedene preko terminala poniÅ¡titi ovu konfiguracijsku datoteku.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">Nastavi</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">Odustanite</translation>
</message>
@@ -1786,7 +2506,11 @@
<source>Current total balance in watch-only addresses</source>
<translation type="unfinished">Trenutno ukupno stanje na iskljuÄivo promatranim adresama</translation>
</message>
- </context>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation type="unfinished">Privatni naÄin aktiviran za tab Pregled. Za prikaz vrijednosti, odznaÄi Postavke -&gt; Sakrij vrijednosti.</translation>
+ </message>
+</context>
<context>
<name>PSBTOperationsDialog</name>
<message>
@@ -1794,6 +2518,91 @@
<translation type="unfinished">Dijalog</translation>
</message>
<message>
+ <source>Sign Tx</source>
+ <translation type="unfinished">Potpiši Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation type="unfinished">Objavi Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation type="unfinished">Kopiraj u međuspremnik</translation>
+ </message>
+ <message>
+ <source>Save…</source>
+ <translation type="unfinished">Spremi...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation type="unfinished">Zatvori</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation type="unfinished">Neuspješno dohvaćanje transakcije: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation type="unfinished">Neuspješno potpisivanje transakcije: %1</translation>
+ </message>
+ <message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Nije moguće potpisati inpute dok je novÄanik zakljuÄan.</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation type="unfinished">Nije bilo moguće potpisati više inputa. </translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation type="unfinished">Potpisano %1 inputa, ali potrebno je još potpisa. </translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation type="unfinished">Transakcija uspješno potpisana. Transakcija je spremna za objavu.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation type="unfinished">Nepoznata greška pri obradi transakcije.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation type="unfinished">Uspješna objava transakcije! ID transakcije: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation type="unfinished">Neuspješna objava transakcije: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation type="unfinished">PBST kopiran u meduspremnik.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation type="unfinished">Spremi podatke transakcije</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">DjelomiÄno potpisana transakcija (binarno)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation type="unfinished">PBST spremljen na disk.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation type="unfinished">* Å alje %1 %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation type="unfinished">Ne mogu izraÄunati naknadu za transakciju niti totalni iznos transakcije.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation type="unfinished">Plaća naknadu za transakciju:</translation>
+ </message>
+ <message>
<source>Total Amount</source>
<translation type="unfinished">Ukupni iznos</translation>
</message>
@@ -1801,7 +2610,39 @@
<source>or</source>
<translation type="unfinished">ili</translation>
</message>
- </context>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation type="unfinished">Transakcija ima %1 nepotpisanih inputa.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation type="unfinished">Transakciji nedostaje informacija o inputima.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation type="unfinished">Transakcija još uvijek treba potpis(e).</translation>
+ </message>
+ <message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Ali nijedan novÄanik nije uÄitan.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation type="unfinished">(Ali ovaj novÄanik ne može potpisati transakcije.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation type="unfinished">(Ali ovaj novÄanik nema odgovarajuće kljuÄeve.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation type="unfinished">Transakcija je cjelovito potpisana i spremna za objavu.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation type="unfinished">Status transakcije je nepoznat.</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
<message>
@@ -1821,6 +2662,14 @@
<translation type="unfinished">'bitcoin://' nije ispravan URI. Koristite 'bitcoin:' umjesto toga.</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.
+Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
+If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation type="unfinished">Nemoguće obraditi zahtjev za plaćanje zato što BIP70 nije podržan.
+S obzirom na Å¡iroko rasprostranjene sigurnosne nedostatke u BIP70, preporuÄljivo je da zanemarite preporuke trgovca u vezi promjene novÄanika.
+Ako imate ovu grešku, od trgovca zatražite URI koji je kompatibilan sa BIP21.</translation>
+ </message>
+ <message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
<translation type="unfinished">Ne može se parsirati URI! Uzrok tomu može biti nevažeća Bitcoin adresa ili neispravni parametri kod URI-a.</translation>
</message>
@@ -1880,6 +2729,10 @@
<context>
<name>QRImageWidget</name>
<message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">&amp;Spremi sliku...</translation>
+ </message>
+ <message>
<source>&amp;Copy Image</source>
<translation type="unfinished">&amp;Kopirajte sliku</translation>
</message>
@@ -1899,7 +2752,12 @@
<source>Save QR Code</source>
<translation type="unfinished">Spremi QR kod</translation>
</message>
- </context>
+ <message>
+ <source>PNG Image</source>
+ <extracomment>Expanded name of the PNG file format. See: https://en.wikipedia.org/wiki/Portable_Network_Graphics.</extracomment>
+ <translation type="unfinished">PNG slika</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -2007,10 +2865,38 @@
<translation type="unfinished">Broj sinkronizranih blokova</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Zadnja transakcija</translation>
+ </message>
+ <message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation type="unfinished">Mapirani Autonomni sustav koji se koristi za diverzifikaciju odabira peer-ova.</translation>
+ </message>
+ <message>
<source>Mapped AS</source>
<translation type="unfinished">Mapirano kao</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Prenosimo li adrese ovom peer-u.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Prijenos adresa</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Obrađene adrese</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Adrese ograniÄene brzinom</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">KorisniÄki agent</translation>
</message>
@@ -2019,6 +2905,10 @@
<translation type="unfinished">Konzola za Ävor</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation type="unfinished">Trenutna visina bloka</translation>
+ </message>
+ <message>
<source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
<translation type="unfinished">Otvorite datoteku zapisa programa %1 iz trenutne podatkovne mape. Može potrajati nekoliko sekundi za velike datoteke zapisa.</translation>
</message>
@@ -2031,14 +2921,59 @@
<translation type="unfinished">Povećajte veliÄinu fonta</translation>
</message>
<message>
+ <source>Permissions</source>
+ <translation type="unfinished">Dopuštenja</translation>
+ </message>
+ <message>
+ <source>The direction and type of peer connection: %1</source>
+ <translation type="unfinished">Smjer i tip peer konekcije: %1</translation>
+ </message>
+ <message>
+ <source>Direction/Type</source>
+ <translation type="unfinished">Smjer/tip</translation>
+ </message>
+ <message>
+ <source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
+ <translation type="unfinished">Mrežni protokoli kroz koje je spojen ovaj peer: IPv4, IPv6, Onion, I2P, ili CJDNS.</translation>
+ </message>
+ <message>
<source>Services</source>
<translation type="unfinished">Usluge</translation>
</message>
<message>
+ <source>Whether the peer requested us to relay transactions.</source>
+ <translation type="unfinished">Je li peer od nas zatražio prijenos transakcija.</translation>
+ </message>
+ <message>
+ <source>Wants Tx Relay</source>
+ <translation type="unfinished">Želi Tx prijenos</translation>
+ </message>
+ <message>
+ <source>High bandwidth BIP152 compact block relay: %1</source>
+ <translation type="unfinished">Visoka razina BIP152 kompaktnog blok prijenosa: %1</translation>
+ </message>
+ <message>
+ <source>High Bandwidth</source>
+ <translation type="unfinished">Visoka razina prijenosa podataka</translation>
+ </message>
+ <message>
<source>Connection Time</source>
<translation type="unfinished">Trajanje veze</translation>
</message>
<message>
+ <source>Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
+ <translation type="unfinished">Vrijeme prošlo od kada je ovaj peer primio novi bloka koji je prošao osnovne provjere validnosti.</translation>
+ </message>
+ <message>
+ <source>Last Block</source>
+ <translation type="unfinished">Zadnji blok</translation>
+ </message>
+ <message>
+ <source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
+ <extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
+ <translation type="unfinished">Vrijeme prošlo od kada je ovaj peer primio novu transakciju koja je prihvaćena u naš mempool.</translation>
+ </message>
+ <message>
<source>Last Send</source>
<translation type="unfinished">Zadnja pošiljka</translation>
</message>
@@ -2103,6 +3038,53 @@
<translation type="unfinished">Izlazne:</translation>
</message>
<message>
+ <source>Inbound: initiated by peer</source>
+ <extracomment>Explanatory text for an inbound peer connection.</extracomment>
+ <translation type="unfinished">Ulazna: pokrenuo peer</translation>
+ </message>
+ <message>
+ <source>Outbound Full Relay: default</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</extracomment>
+ <translation type="unfinished">Izlazni potpuni prijenos: zadano</translation>
+ </message>
+ <message>
+ <source>Outbound Block Relay: does not relay transactions or addresses</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">Izlazni blok prijenos: ne prenosi transakcije ili adrese</translation>
+ </message>
+ <message>
+ <source>Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">PriruÄnik za izlazeće (?): dodano koristeći RPC %1 ili %2/%3 konfiguracijske opcije</translation>
+ </message>
+ <message>
+ <source>Outbound Feeler: short-lived, for testing addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Izlazni ispipavaÄ: kratkotrajan, za testiranje adresa</translation>
+ </message>
+ <message>
+ <source>Outbound Address Fetch: short-lived, for soliciting addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</extracomment>
+ <translation type="unfinished">Dohvaćanje izlaznih adresa: kratkotrajno, za traženje adresa</translation>
+ </message>
+ <message>
+ <source>we selected the peer for high bandwidth relay</source>
+ <translation type="unfinished">odabrali smo peera za brzopodatkovni prijenos</translation>
+ </message>
+ <message>
+ <source>the peer selected us for high bandwidth relay</source>
+ <translation type="unfinished">peer odabran za brzopodatkovni prijenos</translation>
+ </message>
+ <message>
+ <source>no high bandwidth relay selected</source>
+ <translation type="unfinished">brzopodatkovni prijenos nije odabran</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;Kopiraj adresu</translation>
+ </message>
+ <message>
<source>&amp;Disconnect</source>
<translation type="unfinished">&amp;Odspojite</translation>
</message>
@@ -2111,6 +3093,10 @@
<translation type="unfinished">1 &amp;sat</translation>
</message>
<message>
+ <source>1 d&amp;ay</source>
+ <translation type="unfinished">1 d&amp;an</translation>
+ </message>
+ <message>
<source>1 &amp;week</source>
<translation type="unfinished">1 &amp;tjedan</translation>
</message>
@@ -2119,6 +3105,11 @@
<translation type="unfinished">1 &amp;godinu</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">&amp;Kopiraj IP/Netmask</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">&amp;Ukinite zabranu</translation>
</message>
@@ -2135,6 +3126,28 @@
<translation type="unfinished">IzvrÅ¡ava se naredba koristeći novÄanik "%1"</translation>
</message>
<message>
+ <source>Welcome to the %1 RPC console.
+Use up and down arrows to navigate history, and %2 to clear screen.
+Use %3 and %4 to increase or decrease the font size.
+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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Dobrodošli u %1 RPC konzolu.
+Koristite strelice za gore i dolje kako biste navigirali kroz povijest, i %2 za micanje svega sa zaslona.
+Koristite %3 i %4 za smanjivanje i povećavanje veliÄine fonta.
+Utipkajte %5 za pregled svih dosrupnih komandi.
+Za više informacija o korištenju ove konzile, utipkajte %6.
+
+%7UPOZORENJE: Prevaranti su uvijek aktivni te kradu sadržaj novÄanika korisnika tako Å¡to im daju upute koje komande upisati. Nemojte koristiti ovu konzolu bez potpunog razumijevanja posljedica upisivanja komande.%8</translation>
+ </message>
+ <message>
+ <source>Executing…</source>
+ <extracomment>A console message indicating an entered command is currently being executed.</extracomment>
+ <translation type="unfinished">Izvršavam...</translation>
+ </message>
+ <message>
<source>via %1</source>
<translation type="unfinished">preko %1</translation>
</message>
@@ -2159,6 +3172,10 @@
<translation type="unfinished">Zabranite za</translation>
</message>
<message>
+ <source>Never</source>
+ <translation type="unfinished">Nikada</translation>
+ </message>
+ <message>
<source>Unknown</source>
<translation type="unfinished">Nepoznato</translation>
</message>
@@ -2194,6 +3211,10 @@
<translation type="unfinished">Opcionalan iznos koji možete zahtijevati. Ostavite ovo prazno ili unesite nulu ako ne želite zahtijevati specifiÄan iznos.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Neobvezna oznaka za oznaÄavanje nove primateljske adrese (koristi se za identifikaciju raÄuna). TakoÄ‘er je pridružena zahtjevu za plaćanje.</translation>
+ </message>
+ <message>
<source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
<translation type="unfinished">Izborna poruka je priložena zahtjevu za plaćanje i može se prikazati pošiljatelju.</translation>
</message>
@@ -2234,13 +3255,41 @@
<translation type="unfinished">Kopiraj &amp;URI</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopiraj adresu</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiraj &amp;oznaku</translation>
+ </message>
+ <message>
+ <source>Copy &amp;message</source>
+ <translation type="unfinished">Kopiraj &amp;poruku</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopiraj &amp;iznos</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">Ne može se otkljuÄati novÄanik.</translation>
</message>
- </context>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation type="unfinished">Ne mogu generirati novu %1 adresu</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>Request payment to …</source>
+ <translation type="unfinished">Zatraži plaćanje na...</translation>
+ </message>
+ <message>
+ <source>Address:</source>
+ <translation type="unfinished">Adresa:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation type="unfinished">Iznos:</translation>
</message>
@@ -2265,6 +3314,18 @@
<translation type="unfinished">Kopiraj &amp;adresu</translation>
</message>
<message>
+ <source>&amp;Verify</source>
+ <translation type="unfinished">&amp;Verificiraj</translation>
+ </message>
+ <message>
+ <source>Verify this address on e.g. a hardware wallet screen</source>
+ <translation type="unfinished">Verificiraj ovu adresu na npr. zaslonu hardverskog novÄanika</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">&amp;Spremi sliku...</translation>
+ </message>
+ <message>
<source>Payment information</source>
<translation type="unfinished">Informacije o uplati</translation>
</message>
@@ -2395,15 +3456,31 @@
<translation type="unfinished">Obriši sva polja</translation>
</message>
<message>
+ <source>Inputs…</source>
+ <translation type="unfinished">Inputi...</translation>
+ </message>
+ <message>
<source>Dust:</source>
<translation type="unfinished">Prah:</translation>
</message>
<message>
+ <source>Choose…</source>
+ <translation type="unfinished">Odaberi...</translation>
+ </message>
+ <message>
<source>Hide transaction fee settings</source>
<translation type="unfinished">Sakrijte postavke za transakcijske provizije
</translation>
</message>
<message>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation type="unfinished">Zadajte prilagodenu naknadu po kB (1000 bajtova) virtualne veliÄine transakcije.
+
+Napomena: Budući da se naknada raÄuna po bajtu, naknada od "100 satoÅ¡ija po kB" za transakciju veliÄine 500 bajtova (polovica od 1 kB) rezultirala bi ultimativno naknadom od samo 50 satoÅ¡ija.</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">Kada je kapacitet transakcija manja od prostora u blokovima, rudari i Ävorovi prenositelji mogu zatražiti minimalnu naknadu. Prihvatljivo je platiti samo ovu minimalnu naknadu, ali budite svjesni da ovime može nastati transakcija koja se nikad ne potvrÄ‘uje Äim je potražnja za koriÅ¡tenjem Bitcoina veća nego Å¡to mreža može obraditi.</translation>
</message>
@@ -2412,6 +3489,10 @@
<translation type="unfinished">Preniska naknada može rezultirati transakcijom koja se nikad ne potvrÄ‘uje (vidite oblaÄić)</translation>
</message>
<message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks…)</source>
+ <translation type="unfinished">(Pametna procjena naknada joÅ¡ nije inicijalizirana. InaÄe traje nekoliko blokova...)</translation>
+ </message>
+ <message>
<source>Confirmation time target:</source>
<translation type="unfinished">Ciljno vrijeme potvrde:</translation>
</message>
@@ -2472,10 +3553,28 @@
<translation type="unfinished">%1 (%2 blokova)</translation>
</message>
<message>
+ <source>Sign on device</source>
+ <extracomment>"device" usually means a hardware wallet.</extracomment>
+ <translation type="unfinished">Potpiši na uređaju</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">Prvo poveži svoj hardverski novÄanik.</translation>
+ </message>
+ <message>
+ <source>Set external signer script path in Options -&gt; Wallet</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Postavi put za vanjsku skriptu potpisnika u Opcije -&gt; NovÄanik</translation>
+ </message>
+ <message>
<source>Cr&amp;eate Unsigned</source>
<translation type="unfinished">Cr&amp;eate nije potpisan</translation>
</message>
<message>
+ <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
+ <translation type="unfinished">Stvara djelomiÄno potpisanu Bitcoin transakciju (Partially Signed Bitcoin Transaction - PSBT) za upotrebu sa npr. novÄanikom %1 koji nije povezan s mrežom ili sa PSBT kompatibilnim hardverskim novÄanikom.</translation>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation type="unfinished">iz novÄanika '%1'</translation>
</message>
@@ -2488,10 +3587,41 @@
<translation type="unfinished">%1 na %2</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details…"</source>
+ <translation type="unfinished">Kliknite "Prikažite detalje..." kako biste pregledali popis primatelja</translation>
+ </message>
+ <message>
<source>Sign failed</source>
<translation type="unfinished">Potpis nije uspio</translation>
</message>
<message>
+ <source>External signer not found</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Vanjski potpisnik nije pronađen</translation>
+ </message>
+ <message>
+ <source>External signer failure</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Neuspješno vanjsko potpisivanje</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation type="unfinished">Spremi podatke transakcije</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">DjelomiÄno potpisana transakcija (binarno)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation type="unfinished">PSBT spremljen</translation>
+ </message>
+ <message>
+ <source>External balance:</source>
+ <translation type="unfinished">Vanjski balans:</translation>
+ </message>
+ <message>
<source>or</source>
<translation type="unfinished">ili</translation>
</message>
@@ -2500,6 +3630,21 @@
<translation type="unfinished">Možete kasnije povećati naknadu (javlja Replace-By-Fee, BIP-125).</translation>
</message>
<message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Molimo pregledajte svoj prijedlog transakcije. Ovo će stvoriti djelomiÄno potpisanu Bitcoin transakciju (PBST) koju možete spremiti ili kopirati i zatim potpisati sa npr. novÄanikom %1 koji nije povezan s mrežom ili sa PSBT kompatibilnim hardverskim novÄanikom.</translation>
+ </message>
+ <message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Želite li kreirati ovu transakciju?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Molimo pregledajte svoju transakciju. Možete kreirarti i poslati ovu transakciju ili kreirati djelomiÄno potpisanu Bitcoin transakciju (PBST) koju možete spremiti ili kopirati i zatim potpisati sa npr. novÄanikom %1 koji nije povezan s mrežom ili sa PSBT kompatibilnim hardverskim novÄanikom.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Molim vas, pregledajte svoju transakciju.</translation>
@@ -2552,10 +3697,6 @@
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Naknada veća od %1 smatra se apsurdno visokim naknadom.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Zahtjev za plaćanje istekao.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2636,14 +3777,6 @@
<translation type="unfinished">Poruka:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Ovo je neautenticiran zahtjev za plaćanje.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Ovo je autenticiran zahtjev za plaćanje.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Unesite oznaku za ovu adresu kako bi ju dodali u vaš adresar</translation>
</message>
@@ -2651,14 +3784,6 @@
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Poruka koja je dodana uplati: URI koji će biti spremljen s transakcijom za referencu. Napomena: Ova poruka neće biti poslana preko Bitcoin mreže.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Primatelj plaćanja:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Zapis:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -2666,7 +3791,11 @@
<source>Send</source>
<translation type="unfinished">Pošalji</translation>
</message>
- </context>
+ <message>
+ <source>Create Unsigned</source>
+ <translation type="unfinished">Kreiraj nepotpisano</translation>
+ </message>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
@@ -2811,33 +3940,36 @@
</message>
</context>
<context>
- <name>TransactionDesc</name>
- <message>
- <source>conflicted with a transaction with %1 confirmations</source>
- <translation type="unfinished">subokljen s transakcijom broja potvrde %1</translation>
- </message>
+ <name>SplashScreen</name>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/nepotvrđeno, %1</translation>
+ <source>(press q to shutdown and continue later)</source>
+ <translation type="unfinished">(pritisnite q kako bi ugasili i nastavili kasnije)</translation>
</message>
<message>
- <source>in memory pool</source>
- <translation type="unfinished">u memorijskom bazenu</translation>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">pritisnite q za gašenje</translation>
</message>
+</context>
+<context>
+ <name>TransactionDesc</name>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">nije u memorijskom bazenu</translation>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
+ <translation type="unfinished">subokljen s transakcijom broja potvrde %1</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">napušteno</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/nepotvrđeno</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 potvrda</translation>
</message>
<message>
@@ -3138,10 +4270,64 @@
<translation type="unfinished">Min iznos</translation>
</message>
<message>
+ <source>Range…</source>
+ <translation type="unfinished">Raspon...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopiraj adresu</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiraj &amp;oznaku</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopiraj &amp;iznos</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">Kopiraj &amp;ID transakcije</translation>
+ </message>
+ <message>
+ <source>Copy &amp;raw transaction</source>
+ <translation type="unfinished">Kopiraj &amp;sirovu transakciju</translation>
+ </message>
+ <message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">Kopiraj sve transakcijske &amp;detalje</translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">&amp;Prikaži detalje transakcije</translation>
+ </message>
+ <message>
+ <source>Increase transaction &amp;fee</source>
+ <translation type="unfinished">Povećaj transakcijsku &amp;naknadu</translation>
+ </message>
+ <message>
+ <source>A&amp;bandon transaction</source>
+ <translation type="unfinished">&amp;Napusti transakciju</translation>
+ </message>
+ <message>
+ <source>&amp;Edit address label</source>
+ <translation type="unfinished">&amp;Izmjeni oznaku adrese</translation>
+ </message>
+ <message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Prikazi u %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Izvozite povijest transakcija</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Datoteka podataka odvojenih zarezima (*.csv)</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">Potvrđeno</translation>
</message>
@@ -3193,6 +4379,14 @@
<context>
<name>WalletFrame</name>
<message>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation type="unfinished">Nijedan novÄanik nije uÄitan.
+Idi na Datoteka &gt; Otvori novÄanik za uÄitanje novÄanika.
+- ILI -</translation>
+ </message>
+ <message>
<source>Create a new wallet</source>
<translation type="unfinished">Stvorite novi novÄanik</translation>
</message>
@@ -3200,7 +4394,27 @@
<source>Error</source>
<translation type="unfinished">Greška</translation>
</message>
- </context>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation type="unfinished">Nije moguće dekodirati PSBT iz međuspremnika (nevažeći base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation type="unfinished">UÄitaj podatke transakcije</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation type="unfinished">DjelomiÄno potpisana transakcija (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation type="unfinished">PSBT datoteka mora biti manja od 100 MB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation type="unfinished">Nije moguće dekodirati PSBT</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
@@ -3233,6 +4447,10 @@
<translation type="unfinished">Nova naknada:</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Upozorenje: Ovo može platiti dodatnu naknadu smanjenjem change outputa ili dodavanjem inputa, po potrebi. Može dodati novi change output ako jedan već ne postoji. Ove promjene bi mogle smanjiti privatnost.</translation>
+ </message>
+ <message>
<source>Confirm fee bump</source>
<translation type="unfinished">Potvrdite povećanje naknade</translation>
</message>
@@ -3253,6 +4471,10 @@
<translation type="unfinished">Transakcija ne može biti izvršena.</translation>
</message>
<message>
+ <source>Can't display address</source>
+ <translation type="unfinished">Ne mogu prikazati adresu</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">uobiÄajeni novÄanik</translation>
</message>
@@ -3272,6 +4494,11 @@
<translation type="unfinished">Arhiviranje novÄanika</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Podaci novÄanika</translation>
+ </message>
+ <message>
<source>Backup Failed</source>
<translation type="unfinished">Arhiviranje nije uspjelo</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts
index 2bcaac0552..ed7aa6c48c 100644
--- a/src/qt/locale/bitcoin_hu.ts
+++ b/src/qt/locale/bitcoin_hu.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">A cím vagy címke szerkeszteséhez kattintson a jobb gombbal</translation>
+ <translation type="unfinished">A cím vagy címke szerkesztéséhez kattintson a jobb gombbal</translation>
</message>
<message>
<source>Create a new address</source>
@@ -47,11 +47,11 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation type="unfinished">Kedvezményezett címének kiválasztása</translation>
+ <translation type="unfinished">Válassza ki a küldési címet kimenő utalásokhoz</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation type="unfinished">Jóváírási cím kiválasztása</translation>
+ <translation type="unfinished">Válassza ki a fogadó címet beérkező utalásokhoz</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -76,11 +76,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation type="unfinished">&amp;Cím másolása</translation>
+ <translation type="unfinished">Cím &amp;másolása</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation type="unfinished">Másolás és Címkézés</translation>
+ <translation type="unfinished">Másolás és &amp;címkézés</translation>
</message>
<message>
<source>&amp;Edit</source>
@@ -98,7 +98,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
- <translation type="unfinished">Hiba történt a címlista %1 mentésekor. Kérem próbálja újra.</translation>
+ <translation type="unfinished">Hiba történt a címlista %1 mentésekor. Kérem próbálja újra.</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -176,7 +176,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<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">Ãrja be a tárca új jelszavát. &lt;br/&gt;A jelszó összetétele a következÅ‘: &lt;b&gt;tíz vagy annál több véletlenszerű karakter&lt;/b&gt;, vagy &lt;b&gt;nyolc vagy annál több szó&lt;/b&gt;. </translation>
+ <translation type="unfinished">Ãrja be a tárca új jelszavát. &lt;br/&gt;Használjon &lt;b&gt;legalább tíz véletlenszerű karakterbÅ‘l&lt;/b&gt;, vagy &lt;b&gt;legalább nyolc szóból&lt;/b&gt; álló jelszót.</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
@@ -245,6 +245,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">Ajajj, nagy baj van: Runaway exception!</translation>
+ </message>
+ <message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
<translation type="unfinished">Végzetes hiba történt %1 nem tud biztonságban továbblépni így most kilép.</translation>
</message>
@@ -429,11 +433,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
- <translation type="unfinished">Nem sikerült a tárcát %iverzióról %iverzióra vissza módosítani. A tárca verzió változatlan maradt.</translation>
+ <translation type="unfinished">Nem sikerült a tárcát %i verzióról %i verzióra módosítani. A tárca verziója változatlan maradt.</translation>
</message>
<message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
- <translation type="unfinished">Az %s adatkönyvtár nem zárható. A %s valószínűleg fut már.</translation>
+ <translation type="unfinished">Az %s adatkönyvtár nem zárolható. A %s valószínűleg fut már.</translation>
</message>
<message>
<source>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>
@@ -468,10 +472,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Hiba: Régi típusú tárcák csak "legacy", "p2sh-segwit" és "bech32" címformátumokat támogatják</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Hiba: Figyelés a bejövő kapcsolatokra sikertelen (a listen hibaüzenete: %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Díjbecslés sikertelen. Alapértelmezett díj le van tiltva. Várjon néhány blokkot vagy engedélyezze a -fallbackfee -t.</translation>
</message>
@@ -616,6 +616,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nem lehet írni a '%s' könyvtárba; ellenőrizze a jogosultságokat.</translation>
</message>
<message>
+ <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">A -txindex frissítése nem fejezhető be mivel egy korábbi verzió kezdte el. Indítsa újra az előző verziót vagy futtassa a teljes -reindex parancsot.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s kérés figyel a(z) %u porton. Ennek a portnak a megítélése "rossz" ezért valószínűtlen, hogy más Bitcoin Core partner ezen keresztül csatlakozna. Részletekért és teljes listáért lásd doc/p2p-bad-ports.md.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Nem lehetséges a megadott kapcsolatok és az addrman által felderített kapcsolatok egyidejű használata.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Hiba %s betöltése közben: Külső aláíró tárca betöltése külső aláírók támogatása nélkül</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Az érvénytelen peers.dat fájl átnevezése sikertelen. Kérjük mozgassa vagy törölje, majd próbálja újra.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">A konfigurációs beálltás %s kizárólag az %s hálózatra vonatkozik amikor a [%s] szekcióban van.</translation>
</message>
@@ -657,11 +677,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Error initializing block database</source>
- <translation type="unfinished">A blokkadatbázis inicializálása nem sikerült</translation>
+ <translation type="unfinished">A blokkadatbázis előkészítése nem sikerült</translation>
</message>
<message>
<source>Error initializing wallet database environment %s!</source>
- <translation type="unfinished">A tárca-adatbázis inicializálása nem sikerült: %s!</translation>
+ <translation type="unfinished">A tárca-adatbázis előkészítése nem sikerült: %s!</translation>
</message>
<message>
<source>Error loading %s</source>
@@ -696,10 +716,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">A tárca adatbázisból a következő rekord beolvasása sikertelen.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Hiba a blokk adatbázis betöltése közben</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Hiba: Nem tudott kurzort az adatbázisba készíteni</translation>
</message>
@@ -721,7 +737,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Error: Keypool ran out, please call keypoolrefill first</source>
- <translation type="unfinished">A címraktár kiürült, kérjük előbb adja ki a keypoolrefill parancsot.</translation>
+ <translation type="unfinished">A címraktár kiürült, előbb adja ki a keypoolrefill parancsot.</translation>
</message>
<message>
<source>Error: Missing checksum</source>
@@ -757,7 +773,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Ignoring duplicate -wallet %s.</source>
- <translation type="unfinished">A duplikált -wallet %s figyelmen kívül hagyva.</translation>
+ <translation type="unfinished">Az ismétlődő -wallet %s figyelmen kívül hagyva.</translation>
</message>
<message>
<source>Importing…</source>
@@ -848,10 +864,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nincsenek rendelkezésre álló címek</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Proxy szerver nincs megadva. A megadás módja: -proxy=&lt;ip&gt; vagy -proxy=&lt;ip:port&gt;</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Nincs elég fájlleíró.</translation>
</message>
@@ -860,10 +872,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nyesett üzemmódot nem lehet negatív értékkel konfigurálni.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">A Prune mód nem kompatibilis a -coinstatsindex funkcióval.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">A -txindex nem használható nyesett üzemmódban.</translation>
</message>
@@ -964,6 +972,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tranzakció összege nem lehet negatív</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Tartományon kivüli tranzakció visszajáró index</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">A tranzakcóihoz tartozó mempool elődlánc túl hosszú</translation>
</message>
@@ -1036,10 +1048,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nem támogatott naplózási kategória %s=%s</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">UTXO adatbázis frissítése</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">A felhasználói ügynök megjegyzés (%s) veszélyes karaktert tartalmaz.</translation>
</message>
@@ -1100,7 +1108,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Modify configuration options for %1</source>
- <translation type="unfinished">%1 beállítások módosítása</translation>
+ <translation type="unfinished">%1 beállításainak módosítása</translation>
</message>
<message>
<source>Create a new wallet</source>
@@ -1145,7 +1153,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Options…</source>
- <translation type="unfinished">&amp;Opciók…</translation>
+ <translation type="unfinished">&amp;Beállítások…</translation>
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
@@ -1153,7 +1161,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation type="unfinished">A tárcához tartozó privát kulcsok titkosítása</translation>
+ <translation type="unfinished">A tárcádhoz tartozó privát kulcsok titkosítása</translation>
</message>
<message>
<source>&amp;Backup Wallet…</source>
@@ -1169,7 +1177,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Üzenetek aláírása a Bitcoin-címeivel, amivel bizonyíthatja hogy a cím az Öné</translation>
+ <translation type="unfinished">Üzenetek aláírása a Bitcoin-címmeiddel, amivel bizonyítod, hogy a cím a sajátod</translation>
</message>
<message>
<source>&amp;Verify message…</source>
@@ -1362,6 +1370,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nincs elérhető tárca</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Tárca adat</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Tárca neve</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Ablak</translation>
</message>
@@ -1377,6 +1395,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 kliens</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Elrejt</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">&amp;Mutat</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1462,15 +1488,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation type="unfinished">HD kulcs generálás &lt;b&gt;tiltva&lt;/b&gt;</translation>
+ <translation type="unfinished">HD kulcs generálás &lt;b&gt;letiltva&lt;/b&gt;</translation>
</message>
<message>
<source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation type="unfinished">Privát kulcs &lt;b&gt;inaktív&lt;/b&gt;</translation>
+ <translation type="unfinished">Privát kulcs &lt;b&gt;letiltva&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation type="unfinished">A tárca &lt;b&gt;titkosítva&lt;/b&gt; és jelenleg &lt;b&gt;nyitva&lt;/b&gt;.</translation>
+ <translation type="unfinished">A tárca &lt;b&gt;titkosítva&lt;/b&gt; és jelenleg &lt;b&gt;feloldva&lt;/b&gt;.</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
@@ -1485,7 +1511,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>UnitDisplayStatusBarControl</name>
<message>
<source>Unit to show amounts in. Click to select another unit.</source>
- <translation type="unfinished">Egység, amelyben az összegek meg lesznek jelenítve. Kattintson ide, ha másik egységet szeretne kiválasztani.</translation>
+ <translation type="unfinished">Egység, amelyben az összegek lesznek megjelenítve. Kattintson ide másik egység kiválasztásához.</translation>
</message>
</context>
<context>
@@ -1667,7 +1693,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">Nem lehet az aláírókat listázni</translation>
</message>
-</context>
+ </context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1698,7 +1724,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>Open Wallet</source>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
- <translation type="unfinished">Tárca megnyitása</translation>
+ <translation type="unfinished">Tárca Megnyitása</translation>
</message>
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
@@ -1765,7 +1791,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>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>
- <translation type="unfinished">Üres tárca készítése. Az üres tárcák kezdetben nem tartalmaznak privát kulcsokat vagy szkripteket. Később lehetséges a privát kulcsok vagy címek importálása avagy egy HD mag beállítása.</translation>
+ <translation type="unfinished">Üres tárca készítése. Az üres tárcák kezdetben nem tartalmaznak privát kulcsokat vagy szkripteket. Később lehetséges a privát kulcsok vagy címek importálása illetve egy HD mag beállítása.</translation>
</message>
<message>
<source>Make Blank Wallet</source>
@@ -1849,7 +1875,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation type="unfinished">Nem sikerült a tárca felnyitása</translation>
+ <translation type="unfinished">Nem sikerült a tárca feloldása</translation>
</message>
<message>
<source>New key generation failed.</source>
@@ -1864,7 +1890,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>name</source>
- <translation type="unfinished">Név</translation>
+ <translation type="unfinished">név</translation>
</message>
<message>
<source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
@@ -1881,13 +1907,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(a szükséges %1 GB-ból)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB szükséges a teljes lánchoz)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1910,7 +1946,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation type="unfinished">A tárcát is ebben a könyvtárban tároljuk.</translation>
+ <translation type="unfinished">A tárca is ebben a könyvtárban tárolódik.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
@@ -1933,10 +1969,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Mivel ez a program első indulása, megváltoztathatja, hogy a %1 hova mentse az adatokat.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Ha az OK-ra kattint, %1 megkezdi a teljes %4 blokk lánc letöltését és feldolgozását (%2GB) a legkorábbi tranzakciókkal kezdve %3 -ben, amikor a %4 bevezetésre került.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">A blokklánc tárhelyének korlátozása erre:</translation>
</message>
@@ -2049,7 +2081,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Ismeretlen. Fejlécek szinkronizálása (%1, %2%)…</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2210,7 +2242,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
- <translation type="unfinished">A Bitcoin-kliens portjának automatikus megnyitása a routeren. Ez csak akkor működik, ha a routered támogatja az UPnP-t és az engedélyezve is van rajta.</translation>
+ <translation type="unfinished">A Bitcoin-kliens portjának automatikus megnyitása a routeren. Ez csak akkor működik, ha a router támogatja az UPnP-t és az engedélyezve is van rajta.</translation>
</message>
<message>
<source>Map port using &amp;UPnP</source>
@@ -2262,7 +2294,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Show only a tray icon after minimizing the window.</source>
- <translation type="unfinished">Kicsinyítés után csak eszköztár-ikont mutass</translation>
+ <translation type="unfinished">Kicsinyítés után csak az eszköztár-ikont mutassa.</translation>
</message>
<message>
<source>&amp;Minimize to the tray instead of the taskbar</source>
@@ -2270,7 +2302,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>M&amp;inimize on close</source>
- <translation type="unfinished">K&amp;icsinyítés záráskor</translation>
+ <translation type="unfinished">K&amp;icsinyítés bezáráskor</translation>
</message>
<message>
<source>&amp;Display</source>
@@ -2325,10 +2357,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">legjobb találat "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Az itt beállított opciók felülbírálásra kerültek a parancssor vagy a konfigurációs fájl által:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Mégse</translation>
</message>
@@ -2347,14 +2375,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Beállítások törlésének jóváhagyása.</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">A változtatások aktiválásahoz újra kell indítani a klienst.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">A kliens le fog állni. Szeretné folytatni?</translation>
</message>
<message>
@@ -2849,29 +2880,22 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Továbbítsunk-e címeket ennek a partnernek.</translation>
</message>
<message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Cím Továbbítás</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">Az eddig feldolgozott címek összesen, nem számolva a sebességkorlát miatt eldobott címeket.</translation>
- </message>
- <message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">Feldolgozott Címek</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">Sebességkorlát miatt eldobott címek összesen.</translation>
- </message>
- <message>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">Eldobott Címek</translation>
</message>
<message>
@@ -2912,7 +2936,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
- <translation type="unfinished">A hálózati protokoll amin keresztül ez a csomópont kapcsolódik: IPv4, IPv6, Onion, I2P vagy CJDNS.</translation>
+ <translation type="unfinished">A hálózati protokoll amin keresztül ez a partner kapcsolódik: IPv4, IPv6, Onion, I2P vagy CJDNS.</translation>
</message>
<message>
<source>Services</source>
@@ -2940,7 +2964,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
- <translation type="unfinished">A csomóponttól érkező új blokkokra vonatkozó érvényességet igazoló ellenőrzések óta eltelt idő.</translation>
+ <translation type="unfinished">A partnertől érkező új blokkokra vonatkozó érvényességet igazoló ellenőrzések óta eltelt idő.</translation>
</message>
<message>
<source>Last Block</source>
@@ -2949,7 +2973,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<message>
<source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
<extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
- <translation type="unfinished">Az eltelt idő, amióta egy új, a mempoolunkba elfogadott tranzakció érkezett ettől a társtulajdonostól.</translation>
+ <translation type="unfinished">Az eltelt idő, amióta egy új, a saját memóriahalomba elfogadott tranzakció érkezett ettől a partnertől.</translation>
</message>
<message>
<source>Last Send</source>
@@ -3153,7 +3177,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>&amp;Label:</source>
- <translation type="unfinished">Címke:</translation>
+ <translation type="unfinished">Cím&amp;ke:</translation>
</message>
<message>
<source>&amp;Message:</source>
@@ -3237,7 +3261,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation type="unfinished">Nem sikerült a tárca megnyitása</translation>
+ <translation type="unfinished">Nem sikerült a tárca feloldása</translation>
</message>
<message>
<source>Could not generate new %1 address</source>
@@ -3386,7 +3410,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>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>
- <translation type="unfinished">A tartalék díj (failback fee) használata egy órákig, napokig tartó, vagy akár sosem végbemenő tranzakciót eredményezhet. Fontolja meg, hogy Ön adja meg a díjat, vagy várjon amíg a teljes láncot érvényesíti.</translation>
+ <translation type="unfinished">A tartalék díj (fallback fee) használata egy órákig, napokig tartó, vagy akár sosem végbemenő tranzakciót eredményezhet. Fontolja meg, hogy Ön adja meg a díjat, vagy várjon amíg a teljes láncot érvényesíti.</translation>
</message>
<message>
<source>Warning: Fee estimation is currently not possible.</source>
@@ -3661,10 +3685,6 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">A díj magasabb, mint %1 ami abszurd magas díjnak számít.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">A fizetési kérelem lejárt.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3743,14 +3763,6 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
<translation type="unfinished">Ãœzenet:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Ez egy nem hitelesített fizetési kérelem.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Ez egy hitelesített fizetési kérelem.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Adjon egy címkét ehhez a címhez, hogy bekerüljön a használt címek közé</translation>
</message>
@@ -3758,14 +3770,6 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Egy üzenet a bitcoin: URI-hoz csatolva, amely a tranzakciócal együtt lesz eltárolva az Ön számára. Megjegyzés: Ez az üzenet nem kerül elküldésre a Bitcoin hálózaton keresztül.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Címzett:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Jegyzet:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3786,7 +3790,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>&amp;Sign Message</source>
- <translation type="unfinished">Üzenet aláírása...</translation>
+ <translation type="unfinished">Üzenet &amp;Aláírása</translation>
</message>
<message>
<source>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>
@@ -3818,11 +3822,11 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation type="unfinished">Ãœzenet</translation>
+ <translation type="unfinished">Üzenet aláírása, ezzel bizonyítva, hogy Öné ez a Bitcoin cím</translation>
</message>
<message>
<source>Sign &amp;Message</source>
- <translation type="unfinished">Üzenet &amp;aláírása</translation>
+ <translation type="unfinished">Üzenet &amp;Aláírása</translation>
</message>
<message>
<source>Reset all sign message fields</source>
@@ -3830,7 +3834,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>Clear &amp;All</source>
- <translation type="unfinished">Mindent &amp;töröl</translation>
+ <translation type="unfinished">Mindent &amp;Töröl</translation>
</message>
<message>
<source>&amp;Verify Message</source>
@@ -3846,7 +3850,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>The signed message to verify</source>
- <translation type="unfinished">Az aláírt üzenet ellenőrzésre</translation>
+ <translation type="unfinished">Az ellenőrizni kívánt aláírt üzenet</translation>
</message>
<message>
<source>The signature given when the message was signed</source>
@@ -3858,7 +3862,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>Verify &amp;Message</source>
- <translation type="unfinished">Üzenet ellenőrzése</translation>
+ <translation type="unfinished">Üzenet &amp;Ellenőrzése</translation>
</message>
<message>
<source>Reset all verify message fields</source>
@@ -3874,7 +3878,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>Please check the address and try again.</source>
- <translation type="unfinished">Kérem ellenőrizze a címet és próbálja meg újra.</translation>
+ <translation type="unfinished">Ellenőrizze a címet és próbálja meg újra.</translation>
</message>
<message>
<source>The entered address does not refer to a key.</source>
@@ -3906,7 +3910,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>Please check the signature and try again.</source>
- <translation type="unfinished">Kérem ellenőrizze az aláírást és próbálja újra.</translation>
+ <translation type="unfinished">Ellenőrizze az aláírást és próbálja újra.</translation>
</message>
<message>
<source>The signature did not match the message digest.</source>
@@ -3936,30 +3940,22 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">ütközés egy %1 megerősítéssel rendelkező tranzakcióval</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/megerősítetlen, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">a memória halomban</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">nincs a memória halomban</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">elhagyott</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/megerősítetlen</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 megerősítés</translation>
</message>
<message>
@@ -4140,7 +4136,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>Conflicted</source>
- <translation type="unfinished">Konfliktusos</translation>
+ <translation type="unfinished">Ellentmondásos</translation>
</message>
<message>
<source>Immature (%1 confirmations, will be available after %2)</source>
@@ -4168,7 +4164,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>Mined</source>
- <translation type="unfinished">Kibányászva</translation>
+ <translation type="unfinished">Bányászva</translation>
</message>
<message>
<source>watch-only</source>
@@ -4349,7 +4345,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>Exporting Failed</source>
- <translation type="unfinished">Hiba az exportálás során</translation>
+ <translation type="unfinished">Sikertelen Exportálás</translation>
</message>
<message>
<source>There was an error trying to save the transaction history to %1.</source>
@@ -4369,7 +4365,7 @@ Megjegyzés: Mivel a díj bájtonként van kiszámítva, egy "100 satoshi kvB-nk
</message>
<message>
<source>to</source>
- <translation type="unfinished">meddig</translation>
+ <translation type="unfinished">-</translation>
</message>
</context>
<context>
@@ -4512,7 +4508,7 @@ A "Fájl &gt; Tárca megnyitása" menüben tölthet be egyet.
</message>
<message>
<source>Cancel</source>
- <translation type="unfinished">Bezárás</translation>
+ <translation type="unfinished">Mégse</translation>
</message>
</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_id.ts b/src/qt/locale/bitcoin_id.ts
index fe5cfebb54..e37c218d62 100644
--- a/src/qt/locale/bitcoin_id.ts
+++ b/src/qt/locale/bitcoin_id.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">Klik-kanan untuk mengubah alamat atau label</translation>
+ <translation type="unfinished">Klik kanan untuk mengubah alamat atau label</translation>
</message>
<message>
<source>Create a new address</source>
@@ -50,10 +50,6 @@
<translation type="unfinished">Pilih alamat untuk mengirim koin</translation>
</message>
<message>
- <source>Choose the address to receive coins with</source>
- <translation type="unfinished">Piih alamat untuk menerima koin</translation>
- </message>
- <message>
<source>C&amp;hoose</source>
<translation type="unfinished">&amp;Pilih</translation>
</message>
@@ -237,22 +233,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">File pengaturan %1 mungkin rusak atau tidak valid.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Pengecualian pelarian</translation>
</message>
<message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <translation type="unfinished">Kesalahan yang fatal telah terjadi. %1 tidak bisa berlanjut dengan selamat dan akan keluar.</translation>
+ <translation type="unfinished">Error yang fatal telah terjadi. %1 tidak bisa berlanjut dengan selamat dan akan keluar.</translation>
</message>
<message>
<source>Internal error</source>
<translation type="unfinished">Kesalahan internal</translation>
</message>
- <message>
- <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <translation type="unfinished">Terjadi kesalahan internal. %1 akan mencoba melanjutkan secara aman. Ini adalah bug yang tidak terduga yang dapat dilaporkan seperti penjelasan di bawah ini.</translation>
- </message>
-</context>
+ </context>
<context>
<name>QObject</name>
<message>
@@ -347,31 +343,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%ndetik</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n menit</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%njam</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n hari</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nminggu</numerusform>
</translation>
</message>
<message>
@@ -381,7 +377,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n tahun</numerusform>
</translation>
</message>
</context>
@@ -424,6 +420,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kesalahan membaca %s! Semua kunci dibaca dengan benar, tetapi data transaksi atau entri buku alamat mungkin hilang atau salah.</translation>
</message>
<message>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Kesalahan membaca %s! Data transaksi mungkin hilang atau salah. Memindai ulang dompet.</translation>
+ </message>
+ <message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
<translation type="unfinished">Kesalahan: Rekaman pengenal dumpfile salah. Mendapat "%s", diharapkan "format". </translation>
</message>
@@ -440,10 +440,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kesalahan: Dompet lama hanya mendukung jenis alamat "warisan", "p2sh-segwit", dan "bech32"</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Kesalahan: Mendengarkan koneksi yang masuk gagal (dengarkan kesalahan yang dikembalikan %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Estimasi biaya gagal. Biaya fallback dimatikan. Tunggu beberapa blocks atau nyalakan -fallbackfee</translation>
</message>
@@ -480,6 +476,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Pemangkasan dikonfigurasikan di bawah minimum dari %d MiB. Harap gunakan angka yang lebih tinggi.</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">Mode pangkas tidak kompatibel dengan -reindex-chainstate. Gunakan full -reindex sebagai gantinya.</translation>
+ </message>
+ <message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished">Pemangkasan: sinkronisasi dompet terakhir melampaui data yang sudah dipangkas. Anda perlu -reindex (unduh seluruh blockchain lagi jika terjadi node pemangkasan)</translation>
</message>
@@ -528,6 +528,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Format berkas dompet tidak dikenal "%s" tersedia. Berikan salah satu dari "bdb" atau "sqlite". </translation>
</message>
<message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Ditemukan format database chainstate yang tidak didukung. Silakan mulai ulang dengan -reindex-chainstate. Ini akan membangun kembali database chainstate.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Dompet berhasil dibuat. Jenis dompet lama tidak digunakan lagi dan dukungan untuk membuat dan membuka dompet lama akan dihapus di masa mendatang.</translation>
+ </message>
+ <message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
<translation type="unfinished">Peringatan: Dumpfile dompet format "%s" tidak cocok dengan format baris perintah yang ditentukan "%s". </translation>
</message>
@@ -564,6 +572,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tidak bisa menyelesaikan -%s alamat: '%s'</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">Tidak bisa mengatur -forcednsseed ke benar ketika mengatur -dnsseed ke salah</translation>
+ </message>
+ <message>
<source>Cannot set -peerblockfilters without -blockfilterindex.</source>
<translation type="unfinished">Tidak dapat menyetel -peerblockfilters tanpa -blockfilterindex.</translation>
</message>
@@ -572,6 +584,78 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tidak dapat menulis ke direktori data '%s'; periksa izinnya.</translation>
</message>
<message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Opsi -reindex-chainstate tidak kompatibel dengan -blockfilterindex. Harap nonaktifkan blockfilterindex sementara saat menggunakan -reindex-chainstate, atau ganti -reindex-chainstate dengan -reindex untuk membangun kembali semua indeks sepenuhnya.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Opsi -reindex-chainstate tidak kompatibel dengan -coinstatsindex. Harap nonaktifkan sementara coinstatsindex saat menggunakan -reindex-chainstate, atau ganti -reindex-chainstate dengan -reindex untuk membangun kembali semua indeks sepenuhnya.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Opsi -reindex-chainstate tidak kompatibel dengan -txindex. Harap nonaktifkan sementara txindex saat menggunakan -reindex-chainstate, atau ganti -reindex-chainstate dengan -reindex untuk sepenuhnya membangun kembali semua indeks.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Diasumsikan-valid: sinkronisasi dompet terakhir melampaui data blok yang tersedia. Anda harus menunggu rantai validasi latar belakang untuk mengunduh lebih banyak blok.</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Kesalahan: Data buku alamat di dompet tidak dapat diidentifikasi sebagai dompet yang dimigrasikan</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">Kesalahan: Deskriptor duplikat dibuat selama migrasi. Dompet Anda mungkin rusak.</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Kesalahan: %s transaksi di dompet tidak dapat diidentifikasi sebagai dompet yang dimigrasikan</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">Kesalahan: Tidak dapat membuat deskriptor untuk dompet lawas ini. Pastikan dompet tidak terkunci terlebih dahulu</translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">Opsi yang tidak kompatibel: -dnsseed=1 secara eksplisit ditentukan, tetapi -onlynet melarang koneksi ke IPv4/IPv6</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">Koneksi keluar dibatasi untuk Tor (-onlynet=onion) tetapi proxy untuk mencapai jaringan Tor secara eksplisit dilarang: -onion=0</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Koneksi keluar dibatasi untuk Tor (-onlynet=onion) tetapi proxy untuk mencapai jaringan Tor tidak disediakan: tidak ada -proxy, -onion atau -listenonion yang diberikan</translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">Ditemukan deskriptor yang tidak dikenal. Memuat dompet %s
+
+Dompet mungkin telah dibuat pada versi yang lebih baru.
+Silakan coba jalankan versi perangkat lunak terbaru.
+</translation>
+ </message>
+ <message>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished">Level logging khusus kategori yang tidak didukung -loglevel=%s. Diharapkan -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Kategori yang valid: %s. Level log yang valid: %s.</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+Tidak dapat membersihkan migrasi yang gagal</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Tidak dapat memulihkan cadangan dompet..</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Pengaturan konfigurasi untuk %s hanya diterapkan di jaringan %s saat berada di bagian [%s].</translation>
</message>
@@ -648,8 +732,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kesalahan membaca catatan berikutnya dari basis data dompet</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Kesalahan memutakhirkan basis data chainstate</translation>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">Kesalahan: Tidak dapat menambahkan watchonly tx ke dompet watchonly</translation>
+ </message>
+ <message>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">Kesalahan: Tidak dapat menghapus transaksi hanya menonton</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
@@ -664,6 +752,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kesalahan: Checksum dumpfile tidak cocok. Dihitung %s, diharapkan %s</translation>
</message>
<message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">Kesalahan: Gagal membuat dompet baru yang hanya dilihat</translation>
+ </message>
+ <message>
<source>Error: Got key that was not hex: %s</source>
<translation type="unfinished">Kesalahan: Mendapat kunci yang bukan hex: %s</translation>
</message>
@@ -684,10 +776,38 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kesalahan: Tidak ada %s alamat yang tersedia.</translation>
</message>
<message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">Kesalahan: Tidak semua txs watchonly dapat dihapus</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Kesalahan: Dompet ini sudah menggunakan SQLite</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">Kesalahan: Dompet ini sudah menjadi dompet deskriptor</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">Kesalahan: Tidak dapat mulai membaca semua catatan dalam database</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Kesalahan: Tidak dapat membuat cadangan dompet Anda</translation>
+ </message>
+ <message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">Kesalahan: Tidak dapat mengurai versi %u sebagai uint32_t </translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Kesalahan: Tidak dapat membaca semua catatan dalam database</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">Kesalahan: Tidak dapat menghapus data buku alamat yang hanya dilihat</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
<translation type="unfinished">Kesalahan: Tidak dapat menulis catatan ke dompet baru</translation>
</message>
@@ -724,6 +844,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Inisialisasi pemeriksa kewarasan gagal. %s sedang dimatikan.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Input tidak ditemukan atau sudah dibelanjakan</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">Saldo tidak mencukupi</translation>
</message>
@@ -760,6 +884,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Netmask tidak valid yang ditentukan di -whitelist: '%s'</translation>
</message>
<message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">Mendengarkan koneksi masuk gagal (mendengarkan kesalahan yang dikembalikan %s)</translation>
+ </message>
+ <message>
<source>Loading P2P addresses…</source>
<translation type="unfinished">Memuat alamat P2P....</translation>
</message>
@@ -776,12 +904,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Memuat dompet...</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Jumlah tidak ada</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Perlu menentukan port dengan -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Tidak ada server proxy yang ditentukan. Gunakan -proxy=&lt;ip&gt; atau -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Tidak ada alamat tersedia</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -792,10 +924,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Pemangkasan tidak dapat dikonfigurasi dengan nilai negatif.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Mode pangkas tidak kompatibel dengan -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Mode prune tidak kompatibel dengan -txindex</translation>
</message>
@@ -904,10 +1032,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transaksi harus mempunyai paling tidak satu penerima</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Transaksi memerlukan alamat perubahan, tetapi kami tidak dapat membuatnya.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Transaksi terlalu besar</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Tidak dapat mengalokasikan memori untuk -maxsigcachesize: '%s' MiB</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished">Tidak bisa menghubungkan %s di komputer (Penghubung menghasilkan error %s)</translation>
</message>
@@ -920,6 +1056,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tidak dapat membuat berkas PID '%s': %s</translation>
</message>
<message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">Tidak dapat menemukan UTXO untuk input eksternal</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation type="unfinished">Tidak dapat membuat kunci awal</translation>
</message>
@@ -936,6 +1076,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tidak dapat memulai server HTTP. Lihat log debug untuk detailnya.</translation>
</message>
<message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">Tidak dapat membongkar dompet sebelum bermigrasi</translation>
+ </message>
+ <message>
<source>Unknown -blockfilterindex value %s.</source>
<translation type="unfinished">Jumlah -blockfilterindex yang tidak diketahui %s</translation>
</message>
@@ -956,12 +1100,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Aturan baru yang tidak diketahui diaktifkan (bit versi %i)</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">Kategori logging yang tidak didukung %s=%s.</translation>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">Level logging global yang tidak didukung -loglevel=%s. Nilai yang valid: %s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Memutakhirkan basis data UTXO</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Kategori logging yang tidak didukung %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -1089,7 +1233,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Tanda tangani sebuah pesan menggunakan alamat Bitcoin Anda untuk membuktikan bahwa Anda adalah pemiliknya</translation>
+ <translation type="unfinished">Tanda tangani sebuah pesan menggunakan alamat Bitcoin Anda untuk membuktikan bahwa Anda adalah pemilik alamat tersebut</translation>
</message>
<message>
<source>&amp;Verify message…</source>
@@ -1178,7 +1322,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n blok riwayat transaksi diproses.</numerusform>
</translation>
</message>
<message>
@@ -1258,6 +1402,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tutup wallet</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Pulihkan Dompet…</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Pulihkan dompet dari file cadangan</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Tutup semua dompet</translation>
</message>
@@ -1282,6 +1436,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Tidak ada wallet tersedia</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Data Dompet</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Muat Pencadangan Dompet</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Pulihkan Dompet</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nama Dompet</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Jendela</translation>
</message>
@@ -1293,11 +1467,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 klien</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">Sembunyi</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">Tampilkan</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n koneksi yang aktif ke jaringan Bitcoin</numerusform>
</translation>
</message>
<message>
@@ -1321,6 +1503,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">aktifkan aktivitas jaringan</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Pra-Singkronisasi Header (%1%)...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Kesalahan: %1</translation>
</message>
@@ -1559,6 +1745,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">Tidak dapat mencantumkan penandatangan</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Terlalu banyak penanda tangan eksternal ditemukan</translation>
+ </message>
</context>
<context>
<name>LoadWalletsActivity</name>
@@ -1599,6 +1789,34 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Pulihkan Dompet</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Memulihkan Dompet &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Pemulihan dompet gagal</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Peringatan pemulihan dompet</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Pesan pemulihan dompet</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1769,13 +1987,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(dari %1 GB yang dibutuhkan)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n GB ruang tersedia</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB dibutuhkan untuk rantai penuh)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(dari %n GB yang dibutuhkan)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n GB dibutuhkan untuk rantai penuh)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1789,7 +2017,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>(cukup untuk memulihkan cadangan %n hari)</numerusform>
</translation>
</message>
<message>
@@ -1821,10 +2049,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Karena ini adalah pertama kalinya program dijalankan, Anda dapat memilih lokasi %1 akan menyimpan data.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Ketika Anda mengklik OK, %1 akan mulai mengunduh dan memproses %4 block chain penuh (%2GB), dimulai dari transaksi-transaksi awal di %3 saat %4 diluncurkan pertama kali.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Batasi penyimpanan rantai blok menjadi </translation>
</message>
@@ -1841,6 +2065,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Sinkronisasi awal sangat berat dan mungkin akan menunjukkan permasalahan pada perangkat keras komputer Anda yang sebelumnya tidak tampak. Setiap kali Anda menjalankan %1, aplikasi ini akan melanjutkan pengunduhan dari posisi terakhir.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">Ketika Anda mengklik OK, %1 akan mulai mengunduh dan memproses %4 block chain penuh (%2 GB) dimulai dari transaksi-transaksi awal di %3 saat %4 diluncurkan pertama kali.</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished">Apabila Anda memilih untuk membatasi penyimpanan block chain (pruning), data historis tetap akan diunduh dan diproses. Namun, data akan dihapus setelahnya untuk menjaga pemakaian disk agar tetap sedikit.</translation>
</message>
@@ -1933,6 +2161,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Tidak diketahui. Sinkronisasi Header (%1, %2%)...</translation>
</message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Tidak diketahui. Pra-sinkronisasi Header (%1, %2%)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1989,6 +2221,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Minimalisasi aplikasi ketika jendela ditutup. Ketika pilihan ini dipilih, aplikasi akan menutup seluruhnya jika anda memilih Keluar di menu yang tersedia.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Set opsi pengaturan pada jendela dialog ini tertutup oleh baris perintah:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Buka file konfigurasi %1 dari direktori kerja.</translation>
</message>
@@ -2027,10 +2263,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Set nomor thread script verifikasi. Nilai negatif sesuai dengan core yang tidak ingin digunakan di dalam system.</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Ini memungkinkan Anda atau alat pihak ketiga untuk berkomunikasi dengan node melalui perintah baris perintah dan JSON-RPC.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">Aktifkan server R&amp;PC</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">D&amp;ompet</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Apakah akan menetapkan biaya pengurangan dari jumlah sebagai default atau tidak.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Kurangi biaya dari jumlah secara default</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">Ahli</translation>
</message>
@@ -2047,6 +2303,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Perubahan saldo untuk transaksi yang belum dikonfirmasi</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Aktifkan kontrol &amp;PSBT</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Apakah akan menampilkan kontrol PSBT.</translation>
+ </message>
+ <message>
<source>External Signer (e.g. hardware wallet)</source>
<translation type="unfinished">Penandatangan eksternal (seperti dompet perangkat keras)</translation>
</message>
@@ -2147,6 +2413,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Pilihan standar unit yang ingin ditampilkan pada layar aplikasi dan saat mengirim koin.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">URL pihak ketika (misalnya sebuah block explorer) yang mumcul dalam tab transaksi sebagai konteks menu. %s dalam URL diganti dengan kode transaksi. URL dipisahkan dengan tanda vertikal |.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;URL transaksi Pihak Ketiga</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Ingin menunjukkan cara pengaturan koin atau tidak.</translation>
</message>
@@ -2163,10 +2437,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Font spasi tunggal di tab Ringkasan: </translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Set opsi pengaturan pada jendela dialog ini tertutup oleh baris perintah atau dalam konfigurasi file:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;YA</translation>
</message>
@@ -2189,14 +2459,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Memastikan reset pilihan</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Restart klien diperlukan untuk mengaktifkan perubahan.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Pengaturan saat ini akan dicadangkan di "%1".</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Klien akan dimatikan, apakah anda hendak melanjutkan?</translation>
</message>
<message>
@@ -2210,6 +2488,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">File konfigurasi digunakan untuk menspesifikkan pilihan khusus pengguna yang akan menimpa pengaturan GUI. Sebagai tambahan, pengaturan command-line apapun akan menimpa file konfigurasi itu.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">Lanjutkan</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">Batal</translation>
</message>
@@ -2231,6 +2513,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Tidak dapat membaca setelan "%1", %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2336,6 +2625,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Gagal untuk menandatangani transaksi: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Tidak dapat menandatangani input saat dompet terkunci.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">Tidak bisa menandatangani lagi input apapun.</translation>
</message>
@@ -2405,6 +2698,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transaksi masih membutuhkan tanda tangan(s).</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Tapi tidak ada dompet yang dimuat.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Tetapi dompet ini tidak dapat menandatangani transaksi.)</translation>
</message>
@@ -2466,6 +2763,11 @@ Jika Anda menerima kesalahan ini, Anda harus meminta pedagang untuk memberikan U
</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Umur</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Panduan</translation>
@@ -2649,6 +2951,36 @@ Jika Anda menerima kesalahan ini, Anda harus meminta pedagang untuk memberikan U
<translation type="unfinished">AS yang Dipetakan</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Apakah kita menyampaikan alamat ke rekan ini.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Alamat Relay</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Jumlah total alamat yang diterima dari rekan ini yang diproses (tidak termasuk alamat yang dihapus karena pembatasan tarif).</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Jumlah total alamat yang diterima dari rekan ini yang dihapus (tidak diproses) karena pembatasan tarif.</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Alamat Diproses</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Tarif Alamat Terbatas</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Agen Pengguna
@@ -2855,6 +3187,11 @@ Jika Anda menerima kesalahan ini, Anda harus meminta pedagang untuk memberikan U
<translation type="unfinished">1 &amp;tahun</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">&amp;Salin IP/Netmask</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">&amp;Lepas ban</translation>
</message>
@@ -3338,6 +3675,16 @@ Catatan: Karena biaya dihitung berdasarkan per byte, tarif biaya "100 satoshi pe
<translation type="unfinished">Anda dapat menambah biaya kemudian (sinyal Replace-By-Fee, BIP-125).</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Apakah Anda ingin membuat transaksi ini?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Harap untuk analisi proposal transaksi anda kembali. Anda dapat membuat dan mengirim transaksi ini atau membuat transaksi bitcoin yang ditandai tangani sebagaian (PSBT) yang bisa anda simpan atau salin dan tanda tangan dengan contoh dompet offline %1, atau dompet yang kompatibel dengan PSBT</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Mohon periksa kembali transaksi anda.</translation>
@@ -3386,14 +3733,10 @@ Catatan: Karena biaya dihitung berdasarkan per byte, tarif biaya "100 satoshi pe
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Biaya yang lebih tinggi dari %1 dianggap sebagai biaya yang sangat tinggi.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Permintaan pembayaran telah kadaluarsa.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>Diperkirakan akan memulai konfirmasi dalam %n blok.</numerusform>
</translation>
</message>
<message>
@@ -3468,14 +3811,6 @@ Catatan: Karena biaya dihitung berdasarkan per byte, tarif biaya "100 satoshi pe
<translation type="unfinished">Pesan:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Ini permintaan pembayaran yang tidak diautentikasi.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Ini permintaan pembayaran yang diautentikasi.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Masukkan label untuk alamat ini untuk dimasukan dalam daftar alamat yang pernah digunakan</translation>
</message>
@@ -3483,14 +3818,6 @@ Catatan: Karena biaya dihitung berdasarkan per byte, tarif biaya "100 satoshi pe
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Pesan yang dilampirkan ke bitcoin: URI yang akan disimpan dengan transaksi untuk referensi Anda. Catatan: Pesan ini tidak akan dikirim melalui jaringan Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Kirim Ke:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Catatan Peringatan:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3651,33 +3978,46 @@ Catatan: Karena biaya dihitung berdasarkan per byte, tarif biaya "100 satoshi pe
</message>
</context>
<context>
+ <name>SplashScreen</name>
+ <message>
+ <source>(press q to shutdown and continue later)</source>
+ <translation type="unfinished">(tekan q untuk mematikan dan melanjutkan nanti)</translation>
+ </message>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">tekan q untuk mematikan</translation>
+ </message>
+</context>
+<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">Konflik dengan sebuah transaksi dengan %1 konfirmasi</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/belum dikonfirmasi, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">Dalam pool memory</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/belum dikonfirmasi, di kumpulan memori</translation>
</message>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">Tidak dalam pool memory</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/belum dikonfirmasi, tidak di kumpulan memori</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">ditinggalkan</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/belum dikonfirmasi</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 konfirmasi</translation>
</message>
<message>
@@ -3719,7 +4059,7 @@ Catatan: Karena biaya dihitung berdasarkan per byte, tarif biaya "100 satoshi pe
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>matang dalam %n blok lagi</numerusform>
</translation>
</message>
<message>
@@ -3992,6 +4332,11 @@ Catatan: Karena biaya dihitung berdasarkan per byte, tarif biaya "100 satoshi pe
<translation type="unfinished">&amp;Ubah label alamat</translation>
</message>
<message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Menunjukkan %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Ekspor Riwayat Transaksi</translation>
</message>
diff --git a/src/qt/locale/bitcoin_is.ts b/src/qt/locale/bitcoin_is.ts
index 9e5ccb88b0..30d921a07d 100644
--- a/src/qt/locale/bitcoin_is.ts
+++ b/src/qt/locale/bitcoin_is.ts
@@ -601,6 +601,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts
index e573425000..0586176bce 100644
--- a/src/qt/locale/bitcoin_it.ts
+++ b/src/qt/locale/bitcoin_it.ts
@@ -242,6 +242,10 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Il file di impostazioni %1 potrebbe essere corrotto o invalido.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Eccezione runaway</translation>
</message>
@@ -347,36 +351,36 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n secondo</numerusform>
+ <numerusform>%n secondi</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n minuto</numerusform>
+ <numerusform>%n minuti</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n ora</numerusform>
+ <numerusform>%n ore</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n giorno</numerusform>
+ <numerusform>%n giorni</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%nsettimana</numerusform>
+ <numerusform>%nsettimane</numerusform>
</translation>
</message>
<message>
@@ -386,8 +390,8 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n anno</numerusform>
+ <numerusform>%n anni</numerusform>
</translation>
</message>
</context>
@@ -454,10 +458,6 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Errore: i portafogli elettronici obsoleti supportano solo i seguenti tipi di indirizzi: "legacy", "p2sh-segwit", e "bech32"</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Errore: attesa per connessioni in arrivo fallita (errore riportato %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Stima della commissione non riuscita. Fallbackfee è disabilitato. Attendi qualche blocco o abilita -fallbackfee.</translation>
</message>
@@ -602,6 +602,38 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Impossibile scrivere nella directory dei dati ' %s'; controlla le autorizzazioni.</translation>
</message>
<message>
+ <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">L'upgrade -txindex avviato su una versione precedente non può essere completato. Riavviare con la versione precedente o eseguire un -reindex completo.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s richiede di ascoltare sulla porta %u. Questa porta è considerata "cattiva" e quindi è improbabile che qualsiasi peer Bitcoin Core si colleghi ad essa. Guardare doc/p2p-bad-ports.md per i dettagli ed un elenco completo.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Non e' possibile fornire connessioni specifiche e contemporaneamente usare addrman per trovare connessioni uscenti. </translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Errore caricando %s: il wallet del dispositivo esterno di firma é stato caricato senza che il supporto del dispositivo esterno di firma sia stato compilato.</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Mancata rinominazione del file peers.dat non valido. Per favore spostarlo o eliminarlo e provare di nuovo.</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+Non in grado di pulire la migrazione fallita</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Non in grado di ripristinare il backup del portafoglio.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">La configurazione di %s si applica alla rete %s soltanto nella sezione [%s]</translation>
</message>
@@ -682,8 +714,8 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Si è verificato un errore leggendo la voce successiva dal database del portafogli elettronico</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Errore durante l'aggiornamento del database chainstate</translation>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">Errore: Non in grado di rimuovere le transazioni di sola lettura</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
@@ -698,6 +730,10 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Errore: Il Cheksum del dumpfile non corrisponde. Rilevato: %s, sarebbe dovuto essere: %s</translation>
</message>
<message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">Errore: Fallimento nella creazione di un portafoglio nuovo di sola lettura</translation>
+ </message>
+ <message>
<source>Error: Got key that was not hex: %s</source>
<translation type="unfinished">Errore: Ricevuta una key che non ha hex:%s</translation>
</message>
@@ -718,10 +754,22 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Errore: Nessun %s indirizzo disponibile</translation>
</message>
<message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Errore: Questo portafoglio utilizza già SQLite</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Errore: Non in grado di creare un backup del tuo portafoglio</translation>
+ </message>
+ <message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">Errore: impossibile analizzare la versione %u come uint32_t</translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Errore: Non in grado di leggere tutti i record nel database</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
<translation type="unfinished">Errore: non è possibile scrivere la voce nel nuovo portafogli elettronico</translation>
</message>
@@ -830,10 +878,6 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Nessun indirizzo disponibile</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Nessun server proxy specificato. Usa -proxy=&lt;ip&gt; o -proxy=&lt;ip:port&gt;.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Non ci sono abbastanza descrittori di file disponibili.</translation>
</message>
@@ -842,10 +886,6 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">La modalità epurazione non può essere configurata con un valore negativo.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">La modalità epurazione è incompatibile con l'opzione -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">La modalità epurazione è incompatibile con l'opzione -txindex.</translation>
</message>
@@ -946,6 +986,10 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Gli importi di transazione non devono essere negativi</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">La transazione cambia l' indice dell'output fuori dal limite.</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">La transazione ha una sequenza troppo lunga nella mempool</translation>
</message>
@@ -1018,10 +1062,6 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Categoria di registrazione non supportata %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Aggiornamento del database UTXO</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Il commento del User Agent (%s) contiene caratteri non sicuri.</translation>
</message>
@@ -1131,19 +1171,19 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
- <translation type="unfinished">&amp;Cifra il portafoglio...</translation>
+ <translation type="unfinished">&amp;Cripta il portafoglio</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation type="unfinished">Cifra le chiavi private che appartengono al tuo portafoglio</translation>
+ <translation type="unfinished">Cifra le chiavi private che appartengono al tuo portamonete</translation>
</message>
<message>
<source>&amp;Backup Wallet…</source>
- <translation type="unfinished">&amp;Backup Portafoglio...</translation>
+ <translation type="unfinished">&amp;Archivia Wallet...</translation>
</message>
<message>
<source>&amp;Change Passphrase…</source>
- <translation type="unfinished">&amp;Cambia Passphrase...</translation>
+ <translation type="unfinished">&amp;Cambia Frase di sicurezza</translation>
</message>
<message>
<source>Sign &amp;message…</source>
@@ -1236,8 +1276,8 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Processati %n blocchi di cronologia di transazioni.</numerusform>
+ <numerusform> %nblocchi di cronologia di transazioni processati.</numerusform>
</translation>
</message>
<message>
@@ -1274,7 +1314,7 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
</message>
<message>
<source>Load Partially Signed Bitcoin Transaction</source>
- <translation type="unfinished">Carica Partially Signed Bitcoin Transaction</translation>
+ <translation type="unfinished">Carica Transazione Bitcoin Parzialmente Firmata (PSBT)</translation>
</message>
<message>
<source>Load PSBT from &amp;clipboard…</source>
@@ -1317,6 +1357,16 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Chiudi portafoglio</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Ripristina Portafoglio...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Ripristina un portafoglio da un file di backup</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Chiudi tutti i portafogli</translation>
</message>
@@ -1341,6 +1391,26 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Nessun portafoglio disponibile</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Dati del Portafoglio</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Carica Backup del Portafoglio</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Ripristina Portafoglio</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nome Portafoglio</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Finestra</translation>
</message>
@@ -1348,12 +1418,20 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<source>Main Window</source>
<translation type="unfinished">Finestra principale</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Nascondi</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">S&amp;come</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%nconnessione attiva alla rete Bitcoin</numerusform>
+ <numerusform>%nconnessioni attive alla rete Bitcoin</numerusform>
</translation>
</message>
<message>
@@ -1377,6 +1455,10 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Abilita attività di rete</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Pre-sincronizzazione Headers (%1%)…</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Errore: %1</translation>
</message>
@@ -1544,7 +1626,7 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
</message>
<message>
<source>Copy &amp;amount</source>
- <translation type="unfinished">Copia &amp;importo</translation>
+ <translation type="unfinished">Copi&amp;a importo</translation>
</message>
<message>
<source>Copy transaction &amp;ID and output index</source>
@@ -1635,6 +1717,10 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<source>Can't list signers</source>
<translation type="unfinished">Impossibile elencare firmatari</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Troppi firmatari esterni trovati</translation>
+ </message>
</context>
<context>
<name>LoadWalletsActivity</name>
@@ -1675,6 +1761,34 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Ripristina Portafoglio</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Ripristinando Portafoglio &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Ripristino del portafoglio non riuscito</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Avviso di ripristino del portafoglio</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Messaggio di ripristino del portafoglio</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1849,13 +1963,26 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(di %1 GB necessari)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n GB di spazio disponibile</numerusform>
+ <numerusform>%n GB di spazio disponibile</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB necessari per la catena completa)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1902,10 +2029,6 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">Dato che questa è la prima volta che il programma viene lanciato, puoi scegliere dove %1 salverà i suoi dati.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Quando fai click su OK, %1 comincerà a scaricare e processare l'intera %4 catena di blocchi (%2GB) a partire dalla prime transazioni del %3 quando %4 venne inaugurato.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Limita l'archiviazione della catena di blocchi a</translation>
</message>
@@ -2014,7 +2137,7 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Sconosciuto. Sincronizzazione Intestazioni in corso (%1,%2%)…</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2091,7 +2214,7 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
</message>
<message>
<source>Prune &amp;block storage to</source>
- <translation type="unfinished">Eliminare e bloccare l'archiviazione su</translation>
+ <translation type="unfinished">Modalità "prune": elimina i blocchi dal disco dopo</translation>
</message>
<message>
<source>Reverting this setting requires re-downloading the entire blockchain.</source>
@@ -2294,17 +2417,13 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
<translation type="unfinished">corrispondenza più vicina "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Le impostazioni sulla riga di comando o nell'archivio di configurazione hanno precedenza su quelle impostate in questo pannello:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Cancella</translation>
</message>
<message>
<source>Compiled without external signing support (required for external signing)</source>
<extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Compilato senza supporto per firmatario esterno (richiesto per firmare con periferiche)</translation>
+ <translation type="unfinished">Compilato senza supporto per firma esterna (richiesto per firma esterna)</translation>
</message>
<message>
<source>default</source>
@@ -2316,14 +2435,17 @@ E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Conferma ripristino opzioni</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">È necessario un riavvio del client per applicare le modifiche.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Il client sarà arrestato. Si desidera procedere?</translation>
</message>
<message>
@@ -2803,29 +2925,22 @@ Se ricevi questo errore, dovresti richiedere al commerciante di fornire un URI c
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Se gli indirizzi vengono ritrasmessi o meno a questo peer.</translation>
</message>
<message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Trasmissione dell'Indirizzo</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">Numero totale di indirizzi elaborati, esclusi quelli scartati a causa delle limitazioni nella quota.</translation>
- </message>
- <message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">Indirizzi Processati</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">Numero totale di indirizzi scartati a causa delle limitazioni della quota.</translation>
- </message>
- <message>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">Limite di Quota per gli Indirizzi</translation>
</message>
<message>
@@ -3042,6 +3157,10 @@ Se ricevi questo errore, dovresti richiedere al commerciante di fornire un URI c
<translation type="unfinished">Esecuzione del comando senza alcun portafoglio</translation>
</message>
<message>
+ <source>Ctrl+I</source>
+ <translation type="unfinished">Ctrl+W</translation>
+ </message>
+ <message>
<source>Executing command using "%1" wallet</source>
<translation type="unfinished">Esecuzione del comando usando il portafoglio "%1"</translation>
</message>
@@ -3361,7 +3480,7 @@ Per ulteriori informazioni su come usare la console, premi %6.
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation type="unfinished">Cancellare tutti i campi del modulo.</translation>
+ <translation type="unfinished">Cancella tutti i campi del modulo.</translation>
</message>
<message>
<source>Inputs…</source>
@@ -3600,15 +3719,11 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Una commissione maggiore di %1 è considerata irragionevolmente elevata.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Richiesta di pagamento scaduta.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Si stima che la conferma inizi entro %nblocco</numerusform>
+ <numerusform>Si stima che la conferma inizi entro %n blocchi</numerusform>
</translation>
</message>
<message>
@@ -3683,14 +3798,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation type="unfinished">Messaggio:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Questa è una richiesta di pagamento non autenticata.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Questa è una richiesta di pagamento autenticata.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Inserisci un'etichetta per questo indirizzo per aggiungerlo alla lista degli indirizzi utilizzati</translation>
</message>
@@ -3698,11 +3805,7 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Messaggio incluso nel bitcoin URI e che sarà memorizzato con la transazione per tuo riferimento. Nota: Questo messaggio non sarà inviato attraverso la rete Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pagare a:</translation>
- </message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -3766,7 +3869,7 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
</message>
<message>
<source>Clear &amp;All</source>
- <translation type="unfinished">Cancella &amp;Tutto</translation>
+ <translation type="unfinished">Cancell&amp;a Tutto</translation>
</message>
<message>
<source>&amp;Verify Message</source>
@@ -3872,30 +3975,22 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">in conflitto con una transazione con %1 conferme</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/non confermati, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">nella riserva di memoria</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">non nella riserva di memoria</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abbandonato</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/non confermato</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 conferme</translation>
</message>
<message>
@@ -3945,8 +4040,8 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>matura fra %n blocco di più</numerusform>
+ <numerusform>matura fra %n blocchi di più</numerusform>
</translation>
</message>
<message>
@@ -4212,7 +4307,7 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
</message>
<message>
<source>Copy &amp;amount</source>
- <translation type="unfinished">Copia &amp;amount</translation>
+ <translation type="unfinished">Copi&amp;a importo</translation>
</message>
<message>
<source>Copy transaction &amp;ID</source>
@@ -4348,7 +4443,7 @@ Vai su File &gt; Apri Portafoglio per caricare un portafoglio.
<name>WalletModel</name>
<message>
<source>Send Coins</source>
- <translation type="unfinished">Invia Bitcoin</translation>
+ <translation type="unfinished">Invia Monete</translation>
</message>
<message>
<source>Fee bump error</source>
@@ -4405,7 +4500,7 @@ Vai su File &gt; Apri Portafoglio per caricare un portafoglio.
</message>
<message>
<source>default wallet</source>
- <translation type="unfinished">Portafoglio predefinito:</translation>
+ <translation type="unfinished">portafoglio predefinito</translation>
</message>
</context>
<context>
@@ -4416,7 +4511,7 @@ Vai su File &gt; Apri Portafoglio per caricare un portafoglio.
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation type="unfinished">Esporta i dati della tabella corrente in un file</translation>
+ <translation type="unfinished">Esporta su file i dati contenuti nella tabella corrente</translation>
</message>
<message>
<source>Backup Wallet</source>
diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts
index 3e3e7d4329..3b2cd8f19d 100644
--- a/src/qt/locale/bitcoin_ja.ts
+++ b/src/qt/locale/bitcoin_ja.ts
@@ -373,31 +373,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform>%n 秒</numerusform>
+ <numerusform />
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform>%n 分</numerusform>
+ <numerusform />
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform>%n 時間</numerusform>
+ <numerusform />
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform>%n æ—¥</numerusform>
+ <numerusform />
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform>%n 週</numerusform>
+ <numerusform />
</translation>
</message>
<message>
@@ -407,7 +407,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform>%n å¹´</numerusform>
+ <numerusform />
</translation>
</message>
<message>
@@ -478,10 +478,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">エラー: レガシーウォレットã¯ã€ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚¿ã‚¤ãƒ—「legacyã€ãŠã‚ˆã³ã€Œp2sh-segwitã€ã€ã€Œbech32ã€ã®ã¿ã‚’サãƒãƒ¼ãƒˆã—ã¾ã™</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">エラー: 内å‘ãã®æŽ¥ç¶šã‚’リッスンã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸï¼ˆ%s エラーãŒè¿”å´ã•ã‚Œã¾ã—ãŸï¼‰</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">手数料推定ã«å¤±æ•—ã—ã¾ã—ãŸã€‚代替手数料ãŒç„¡åŠ¹ã§ã™ã€‚数ブロック待ã¤ã‹ã€-fallbackfee オプションを有効ã«ã—ã¦ãã ã•ã„。</translation>
</message>
@@ -630,6 +626,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">以å‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§é–‹å§‹ã•ã‚ŒãŸ -txindex アップグレードを完了ã§ãã¾ã›ã‚“。 以å‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§å†èµ·å‹•ã™ã‚‹ã‹ã€ -reindex を実行ã—ã¦ãã ã•ã„。</translation>
</message>
<message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">%s ã®ãƒ­ãƒ¼ãƒ‰ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸï¼šå¤–​​部署å者ウォレットãŒãƒ­ãƒ¼ãƒ‰ã•ã‚Œã¦ã„ã¾ã™</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">%s ã®è¨­å®šã¯ã€ [%s] セクションã«æ›¸ã‹ã‚ŒãŸå ´åˆã®ã¿ %s ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸é©ç”¨ã•ã‚Œã¾ã™ã€‚</translation>
</message>
@@ -706,10 +706,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ウォレットデータベースã‹ã‚‰æ¬¡ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®èª­ã¿å–ã‚Šã§ã‚¨ãƒ©ãƒ¼</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">chainstate データベースã®æ›´æ–°æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">エラー: データベースã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’作æˆã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
</message>
@@ -858,10 +854,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">アドレスãŒä½¿ãˆã¾ã›ã‚“</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">プロキシサーãƒãƒ¼ãŒæŒ‡å®šã•ã‚Œã¦ã¾ã›ã‚“. -proxy=&lt;ip&gt; ã‹ -proxy=&lt;ip:port&gt; を使用ã—ã¦ãã ã•ã„.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">使用å¯èƒ½ãªãƒ•ã‚¡ã‚¤ãƒ«ãƒ‡ã‚£ã‚¹ã‚¯ãƒªãƒ—ã‚¿ãŒä¸è¶³ã—ã¦ã„ã¾ã™ã€‚</translation>
</message>
@@ -870,10 +862,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">剪定モードã®è¨­å®šå€¤ã¯è² ã®å€¤ã«ã¯ã§ãã¾ã›ã‚“。</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">剪定モード㯠-txindex オプションã¨äº’æ›æ€§ãŒã‚ã‚Šã¾ã›ã‚“。</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">剪定モード㯠-txindex オプションã¨äº’æ›æ€§ãŒã‚ã‚Šã¾ã›ã‚“。</translation>
</message>
@@ -1050,10 +1038,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„ログカテゴリ %s=%s 。</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">UTXOデータベースã®æ›´æ–°ä¸­</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">ユーザエージェントã®ã‚³ãƒ¡ãƒ³ãƒˆ ( %s ) ã«å®‰å…¨ã§ãªã„文字ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚</translation>
</message>
@@ -1272,7 +1256,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform>%n ブロックã®å–引履歴を処ç†ã—ã¾ã—ãŸã€‚</numerusform>
+ <numerusform />
</translation>
</message>
<message>
@@ -1376,6 +1360,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ウォレットã¯åˆ©ç”¨ã§ãã¾ã›ã‚“</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">ウォレットデータ</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">ウォレットå</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">ウィンドウ (&amp;W)</translation>
</message>
@@ -1403,7 +1397,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform>Bitcoin Networkã¸ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªæŽ¥ç¶šæ•°: %n</numerusform>
+ <numerusform />
</translation>
</message>
<message>
@@ -1689,7 +1683,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">ç½²å者をリストã§ãã¾ã›ã‚“</translation>
</message>
-</context>
+ </context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1903,17 +1897,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
- <message>
- <source>%1 GB of space available</source>
- <translation type="unfinished">%1 GBã®ç©ºã容é‡ãŒåˆ©ç”¨å¯èƒ½</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(内 %1 GB ãŒå¿…è¦)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(フルãƒã‚§ãƒ¼ãƒ³ã«ã¯ %1 GB ãŒå¿…è¦)</translation>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1927,7 +1927,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform>(%n æ—¥å‰ã®ãƒãƒƒã‚¯ã‚¢ãƒƒãƒ—を復元ã™ã‚‹ã®ã«å……分ã§ã™)</numerusform>
+ <numerusform />
</translation>
</message>
<message>
@@ -1959,10 +1959,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ã“ã‚Œã¯ãƒ—ログラムã®æœ€åˆã®èµ·å‹•ã§ã™ã€‚%1 ãŒãƒ‡ãƒ¼ã‚¿ã‚’ä¿å­˜ã™ã‚‹å ´æ‰€ã‚’é¸æŠžã—ã¦ãã ã•ã„。</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">OKをクリックã™ã‚‹ã¨ã€%1 㯠%4 ãŒãƒªãƒªãƒ¼ã‚¹ã•ã‚ŒãŸ%3å¹´ã«ãŠã‘る最åˆã®å–引ã‹ã‚‰ã®å®Œå…¨ãª %4 ブロックãƒã‚§ãƒ¼ãƒ³ï¼ˆ%2GB)ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ãŠã‚ˆã³å‡¦ç†ã‚’開始ã—ã¾ã™ã€‚</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">ブロックãƒã‚§ãƒ¼ãƒ³ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã‚’次ã«é™å®šã™ã‚‹: </translation>
</message>
@@ -2067,7 +2063,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">ä¸æ˜Žã€‚ヘッダ (%1, %2%) ã®åŒæœŸä¸­â€¦</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2351,10 +2347,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">最もマッãƒã™ã‚‹ "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">ã“ã®ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ã§æŒ‡å®šã—ãŸã‚ªãƒ—ションã¯ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚„設定ファイルã®å†…容ã§ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã•ã‚Œã¾ã™:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">キャンセル(&amp;C)</translation>
</message>
@@ -2373,14 +2365,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">設定リセットã®ç¢ºèª</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">変更を有効化ã™ã‚‹ã«ã¯ã‚¯ãƒ©ã‚¤ã‚¢ãƒ³ãƒˆã‚’å†èµ·å‹•ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">クライアントを終了ã—ã¾ã™ã€‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ</translation>
</message>
<message>
@@ -2873,29 +2868,22 @@ BIP70ã«ã¯åºƒç¯„ãªã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ¼ä¸Šã®å•é¡ŒãŒã‚ã‚‹ã®ã§ã€ã‚¦ã‚©ãƒ¬
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">ã“ã®ãƒ”ã‚¢ã«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’中継ã™ã‚‹ã‹å¦ã‹ã€‚</translation>
</message>
<message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">アドレスã®ä¸­ç¶™</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">レート制é™ã®ãŸã‚ã«é™¤å¤–ã•ã‚ŒãŸã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’除ãã€å‡¦ç†ã•ã‚ŒãŸã‚¢ãƒ‰ãƒ¬ã‚¹ã®ç·æ•°ã€‚</translation>
- </message>
- <message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">処ç†ã•ã‚ŒãŸã‚¢ãƒ‰ãƒ¬ã‚¹</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">レート制é™ã®ãŸã‚ã«é™¤å¤–ã•ã‚ŒãŸã‚¢ãƒ‰ãƒ¬ã‚¹ã®ç·æ•°ã€‚</translation>
- </message>
- <message>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">レート制é™å¯¾è±¡ã®ã‚¢ãƒ‰ãƒ¬ã‚¹</translation>
</message>
<message>
@@ -3702,14 +3690,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">%1 よりも高ã„手数料ã¯ã€ç•°å¸¸ã«é«˜ã™ãŽã§ã™ã€‚</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">支払ã„リクエストãŒæœŸé™åˆ‡ã‚Œã§ã™ã€‚</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform>%n ブロック以内ã«æ‰¿èªãŒé–‹å§‹ã•ã‚Œã‚‹è¦‹è¾¼ã¿ã§ã™ã€‚</numerusform>
+ <numerusform />
</translation>
</message>
<message>
@@ -3784,14 +3768,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">メッセージ:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">ã“ã‚Œã¯æœªèªè¨¼ã®æ”¯æ‰•ã„リクエストã§ã™ã€‚</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">ã“ã‚Œã¯èªè¨¼æ¸ˆã¿ã®æ”¯æ‰•ã„リクエストã§ã™ã€‚</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">ã“ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã«å¯¾ã™ã‚‹ãƒ©ãƒ™ãƒ«ã‚’入力ã™ã‚‹ã“ã¨ã§ã€é€é‡‘ã—ãŸã“ã¨ãŒã‚るアドレスã®ä¸€è¦§ã«è¿½åŠ ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™</translation>
</message>
@@ -3799,14 +3775,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">bitcoin URIã«æ·»ä»˜ã•ã‚Œã¦ã„ãŸãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã§ã™ã€‚ã“ã‚Œã¯å‚照用ã¨ã—ã¦å–引ã¨ã¨ã‚‚ã«ä¿å­˜ã•ã‚Œã¾ã™ã€‚注æ„: メッセージ㯠Bitcoin ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ä¸Šã¸é€ä¿¡ã•ã‚Œã¾ã›ã‚“。</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">é€é‡‘å…ˆ:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">メモ:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3984,30 +3952,22 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">%1 承èªã®å–引ã¨è¡çª</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/未承èª, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">メモリプール内</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">メモリプール外</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">é€ä¿¡ä¸­æ­¢</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/未承èª</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 承èª</translation>
</message>
<message>
@@ -4057,7 +4017,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform>ã‚㨠%n ブロックã§ç†Ÿæˆã—ã¾ã™</numerusform>
+ <numerusform />
</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts
index c0820471b9..afe6c50245 100644
--- a/src/qt/locale/bitcoin_ka.ts
+++ b/src/qt/locale/bitcoin_ka.ts
@@ -70,6 +70,12 @@
<translation type="unfinished">ეს áƒáƒ áƒ˜áƒ¡ თქვენი ბიტკáƒáƒ˜áƒœ-მისáƒáƒ›áƒáƒ áƒ—ები, რáƒáƒ›áƒ”ლთáƒáƒ’áƒáƒœáƒáƒª შეგიძლიáƒáƒ— გáƒáƒ“áƒáƒ®áƒ“áƒ. áƒáƒ£áƒªáƒ˜áƒšáƒ”ბლáƒáƒ“ შეáƒáƒ›áƒáƒ¬áƒ›áƒ”თ თáƒáƒœáƒ®áƒ დრმიმღები მისáƒáƒ›áƒáƒ áƒ—ი გáƒáƒ’ზáƒáƒ•áƒœáƒáƒ›áƒ“ე.</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">ეს თქვენი ბიტკáƒáƒ˜áƒœáƒ˜áƒ¡ მიმღები მიმსáƒáƒ›áƒáƒ áƒ—ებიáƒ. ისáƒáƒ áƒ’ებლეთ ღილáƒáƒ™áƒ˜áƒ— "შექმენით áƒáƒ®áƒáƒšáƒ˜ მიმღები მისáƒáƒ›áƒáƒ áƒ—ები", რáƒáƒ”მლიც მáƒáƒªáƒ”მულირმიმღების ჩáƒáƒœáƒáƒ áƒ—ში áƒáƒ®áƒáƒšáƒ˜ მისáƒáƒ›áƒáƒ áƒ—ების შესáƒáƒ¥áƒ›áƒœáƒ”ლáƒáƒ“.
+ხელმáƒáƒ¬áƒ”რრმხáƒáƒšáƒáƒ“ "მემკვიდრეáƒáƒ‘ის" ტიპის მისáƒáƒ›áƒáƒ áƒ—ებთáƒáƒœáƒáƒ შესáƒáƒ«áƒšáƒ”ბელიáƒ</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">მისáƒáƒ›áƒáƒ áƒ—ის კáƒáƒžáƒ˜áƒ áƒ”ბáƒ</translation>
</message>
@@ -86,6 +92,11 @@
<translation type="unfinished">მისáƒáƒ›áƒáƒ áƒ—ების სიის ექსპáƒáƒ áƒ¢áƒ˜</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">CSV (სპეციáƒáƒšáƒ£áƒ áƒ˜ ტექსტური ფáƒáƒ˜áƒšáƒ˜)</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">მისáƒáƒ›áƒáƒ áƒ—ების სიის %1 შენáƒáƒ®áƒ•áƒ ვერ მáƒáƒ®áƒ”რხდáƒ. გáƒáƒ˜áƒ›áƒ”áƒáƒ áƒ”თ მცდელáƒáƒ‘áƒ.</translation>
@@ -846,6 +857,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -1039,10 +1071,12 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">დáƒáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”თ პáƒáƒ áƒáƒ›áƒ”ტრების დáƒáƒ‘რუნებრნáƒáƒ’ულისხმევზე</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">ცვლილებები ძáƒáƒšáƒáƒ¨áƒ˜ შევრკლიენტის ხელáƒáƒ®áƒáƒšáƒ˜ გáƒáƒ¨áƒ•áƒ”ბის შემდეგ.</translation>
</message>
<message>
@@ -1576,14 +1610,6 @@
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">მესიჯი, რáƒáƒ›áƒ”ლიც თáƒáƒœ ერთვის მáƒáƒœáƒ”ტებს: URI, რáƒáƒ›áƒ”ლიც შეინáƒáƒ®áƒ”ბრტრáƒáƒœáƒ¡áƒáƒ¥áƒªáƒ˜áƒáƒ¡áƒ—áƒáƒœ ერთáƒáƒ“ თქვენთვის. შენიშვნáƒ: მესიჯი áƒáƒ  გáƒáƒ§áƒ•áƒ”ბრგáƒáƒ“áƒáƒ®áƒ“áƒáƒ¡ ბითქáƒáƒ˜áƒœáƒ˜áƒ¡ ქსელში.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">áƒáƒ“რესáƒáƒ¢áƒ˜:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">შენიშვნáƒ:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1704,10 +1730,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/დáƒáƒ£áƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბელიáƒ</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბულიáƒ</translation>
</message>
<message>
@@ -1963,6 +1991,11 @@
<translation type="unfinished">ტრáƒáƒœáƒ¡áƒáƒ¥áƒªáƒ˜áƒ”ბის ისტáƒáƒ áƒ˜áƒ˜áƒ¡ ექსპáƒáƒ áƒ¢áƒ˜</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">CSV (სპეციáƒáƒšáƒ£áƒ áƒ˜ ტექსტური ფáƒáƒ˜áƒšáƒ˜)</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბულიáƒ</translation>
</message>
diff --git a/src/qt/locale/bitcoin_kk.ts b/src/qt/locale/bitcoin_kk.ts
index 5461e6dbab..c9e9387b1a 100644
--- a/src/qt/locale/bitcoin_kk.ts
+++ b/src/qt/locale/bitcoin_kk.ts
@@ -606,6 +606,10 @@
<translation type="unfinished">РаÑÑ‚Ñ‹Ò›</translation>
</message>
<message>
+ <source>yes</source>
+ <translation type="unfinished">Иа</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(белгі жоқ)</translation>
</message>
@@ -646,6 +650,27 @@
<translation type="unfinished">Биткоин</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -659,7 +684,7 @@
</message>
<message>
<source>Error</source>
- <translation type="unfinished">Қате</translation>
+ <translation type="unfinished">қате</translation>
</message>
<message>
<source>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>
@@ -690,7 +715,7 @@
</message>
<message>
<source>Error</source>
- <translation type="unfinished">Қате</translation>
+ <translation type="unfinished">қате</translation>
</message>
</context>
<context>
@@ -815,10 +840,6 @@
<context>
<name>TransactionDesc</name>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/раÑталмаған, %1</translation>
- </message>
- <message>
<source>Date</source>
<translation type="unfinished">Күні</translation>
</message>
@@ -889,7 +910,7 @@
</message>
<message>
<source>Error</source>
- <translation type="unfinished">Қате</translation>
+ <translation type="unfinished">қате</translation>
</message>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_kl.ts b/src/qt/locale/bitcoin_kl.ts
index facce35f99..14f7391759 100644
--- a/src/qt/locale/bitcoin_kl.ts
+++ b/src/qt/locale/bitcoin_kl.ts
@@ -206,6 +206,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_km.ts b/src/qt/locale/bitcoin_km.ts
index e8c469c133..3e4ff7e316 100644
--- a/src/qt/locale/bitcoin_km.ts
+++ b/src/qt/locale/bitcoin_km.ts
@@ -570,6 +570,11 @@
<translation type="unfinished">មិនមានកាបូបអáŸáž¡áž·áž…ážáŸ’រូនិច</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">ឈ្មោះកាបូប</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;វិនដូ</translation>
</message>
@@ -812,6 +817,27 @@
<translation type="unfinished">ប៊ីážážáž‰</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -961,10 +987,12 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">បញ្ចាក់ជម្រើសការកែសម្រួលឡើងវិញ</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">ផ្ទាំងអážáž·ážáž·áž‡áž“áž“áž·áž„ážáŸ’រូវបិទ។ ážáž¾áž¢áŸ’នកចង់បន្ážáž‘ៀážáž«áž‘áŸ?</translation>
</message>
<message>
@@ -1594,10 +1622,6 @@
<source>Transaction creation failed!</source>
<translation type="unfinished">បង្កើážáž”្រážáŸ’ážáž·áž”ážáŸ’ážáž·áž€áž¶ážšáž˜áž·áž“ជោគជáŸáž™!</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">សំណើរទូរទាážáŸ‹áž”្រាក់បានផុážáž€áŸ†ážŽážáŸ‹áŸ”</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -1649,26 +1673,10 @@
<translation type="unfinished">សារៈ</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">áž“áŸáŸ‡áž‡áž¶ážŸáŸ†ážŽáž¾ážšáž‘ូរទាážáŸ‹áž”្រាក់មិនទាន់បានបញ្ចាក់ážáž¶áž˜áž…្បាប់ážáŸ’រឹមážáŸ’រូវ។</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">áž“áŸáŸ‡áž‡áž¶ážŸáŸ†ážŽáž¾ážšáž‘ូរទាážáŸ‹áž”្រាក់ដែលបានបញ្ចាក់ážáž¶áž˜áž…្បាប់ážáŸ’រឹមážáŸ’រូវ។</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">បញ្ចូលស្លាក​សញ្ញាមួយ សម្រាប់អាសយដ្ឋាននáŸáŸ‡ ដើម្បីបញ្ចូលវាទៅក្នងបញ្ចីរអាសយដ្ឋានដែលបានប្រើប្រាស់</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">បង់ទៅកាន់</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">អនុស្សរណៈ</translation>
- </message>
-</context>
+ </context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -1803,6 +1811,7 @@
<name>TransactionDesc</name>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">បានបោះបង់ចោល</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_ko.ts b/src/qt/locale/bitcoin_ko.ts
index f335deb009..9137d07ed4 100644
--- a/src/qt/locale/bitcoin_ko.ts
+++ b/src/qt/locale/bitcoin_ko.ts
@@ -3,11 +3,11 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">지갑 주소나 ë¼ë²¨ì„ 수정하려면 ìš°í´ë¦­ì„ 하십시오.</translation>
+ <translation type="unfinished">ìš°í´ë¦­í•˜ì—¬ 주소나 ìƒí‘œ 수정하기</translation>
</message>
<message>
<source>Create a new address</source>
- <translation type="unfinished">새로운 지갑 주소 ìƒì„±</translation>
+ <translation type="unfinished">새로운 주소 ìƒì„± </translation>
</message>
<message>
<source>&amp;New</source>
@@ -51,7 +51,7 @@
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation type="unfinished">ì½”ì¸ì„ ë°›ì„ ì£¼ì†Œë¥¼ ì„ íƒí•˜ì‹­ì‹œì˜¤.</translation>
+ <translation type="unfinished">ì½”ì¸ì„ ë°›ì„ ì£¼ì†Œë¥¼ ì„ íƒí•˜ì‹­ì‹œì˜¤</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -153,7 +153,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unlock wallet</source>
- <translation type="unfinished">지갑 ìž ê¸ˆì„ í•´ì œ</translation>
+ <translation type="unfinished">지갑 잠금 해제</translation>
</message>
<message>
<source>Change passphrase</source>
@@ -169,7 +169,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation type="unfinished">지갑 암호화를 허용하시겠습니까?</translation>
+ <translation type="unfinished">ì •ë§ë¡œ ì§€ê°‘ì„ ì•”í˜¸í™”í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
</message>
<message>
<source>Wallet encrypted</source>
@@ -246,6 +246,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">%1íŒŒì¼ ì„¸íŒ…ì´ ìž˜ëª»ë˜ì—ˆê±°ë‚˜ 유효하지 않습니다.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">ëŸ°ì–´ì›¨ì´ ì˜ˆì™¸</translation>
</message>
@@ -265,6 +269,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">초기값으로 리셋하거나 ë³€ë™ì‚¬í•­ì—†ì´ 진행하시겠습니까?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">심ê°í•œ 문제가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤. 세팅 파ì¼ì´ 작성가능한지 확ì¸í•˜ê±°ë‚˜ ì„¸íŒ…ì—†ì´ ì‹¤í–‰ì„ ì‹œë„해보세요.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">오류: 지정한 ë°ì´í„° í´ë” "%1"ì€ ì¡´ìž¬í•˜ì§€ 않습니다.</translation>
</message>
@@ -431,10 +445,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">-maxtxfee ê°’ì´ ë„ˆë¬´ í½ë‹ˆë‹¤! í•˜ë‚˜ì˜ ê±°ëž˜ì— ë„ˆë¬´ í° ìˆ˜ìˆ˜ë£Œê°€ 지불 ë©ë‹ˆë‹¤.</translation>
</message>
<message>
+ <source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
+ <translation type="unfinished">%i버젼ì—ì„œ %i버젼으로 다운그레ì´ë“œ í•  수 없습니다. 월렛 ë²„ì ¼ì€ ë³€ê²½ë˜ì§€ 않았습니다.</translation>
+ </message>
+ <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation type="unfinished">ë°ì´í„° 디렉토리 %s ì— ë½ì„ 걸 수 없었습니다. %sê°€ ì´ë¯¸ 실행 ì¤‘ì¸ ê²ƒìœ¼ë¡œ 보입니다.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">사전분리 키풀를 지ì›í•˜ê¸° 위해서 업그레ì´ë“œ 하지 않고는 Non HD split ì§€ê°‘ì˜ %ië²„ì ¼ì„ %i버젼으로 업그레ì´ë“œ í•  수 없습니다. %ië²„ì ¼ì„ í™œìš©í•˜ê±°ë‚˜ 구체화ë˜ì§€ ì•Šì€ ë²„ì ¼ì„ í™œìš©í•˜ì„¸ìš”.</translation>
+ </message>
+ <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation type="unfinished">MIT 소프트웨어 ë¼ì´ì„¼ìŠ¤ì— ë”°ë¼ ë°°í¬ë˜ì—ˆìŠµë‹ˆë‹¤. 첨부 íŒŒì¼ %s ë˜ëŠ” %sì„ ì°¸ì¡°í•˜ì‹­ì‹œì˜¤.</translation>
</message>
@@ -443,22 +465,54 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%s 불러오기 오류! 주소 키는 ëª¨ë‘ ì •í™•í•˜ê²Œ 로드ë˜ì—ˆìœ¼ë‚˜ 거래 ë°ì´í„°ì™€ ì£¼ì†Œë¡ í•„ë“œì—ì„œ 누ë½ì´ë‚˜ 오류가 존재할 수 있습니다.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">오류: 들어오는 ì—°ê²°ì„ í—ˆìš©í•˜ëŠ”ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤ (리슨 오류: %s)</translation>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">%s를 ì½ëŠ”ë° ì—러가 ìƒê²¼ìŠµë‹ˆë‹¤. 트랜잭션 ë°ì´í„°ê°€ 잘못ë˜ì—ˆê±°ë‚˜ 누ë½ë˜ì—ˆìŠµë‹ˆë‹¤. ì§€ê°‘ì„ ë‹¤ì‹œ 스ìºë‹í•©ë‹ˆë‹¤.</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
+ <translation type="unfinished">오류 : ë¤í”„íŒŒì¼ í¬ë§· 기ë¡ì´ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤. "í¬ë§·"ì´ ì•„ë‹ˆë¼ "%s"를 얻었습니다.</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile identifier record is incorrect. Got "%s", expected "%s".</source>
+ <translation type="unfinished">오류 : ë¤í”„íŒŒì¼ ì‹ë³„ìž ê¸°ë¡ì´ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤. "%s"ì´ ì•„ë‹Œ "%s"를 얻었습니다.</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
+ <translation type="unfinished">오류 : ë¤í”„íŒŒì¼ ë²„ì ¼ì´ ì§€ì›ë˜ì§€ 않습니다. ì´ ë¹„íŠ¸ì½”ì¸ ì§€ê°‘ ë²„ì ¼ì€ ì˜¤ì§ ë²„ì ¼1ì˜ ë¤í”„파ì¼ì„ 지ì›í•©ë‹ˆë‹¤. %së²„ì ¼ì˜ ë¤í”„파ì¼ì„ 얻었습니다.</translation>
+ </message>
+ <message>
+ <source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
+ <translation type="unfinished">오류 : 레거시 지갑주소는 "레거시", "p2sh-segwit", "bech32" 지갑 ì£¼ì†Œì˜ íƒ€ìž…ë§Œ 지ì›í•©ë‹ˆë‹¤.</translation>
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">수수료 ì¶”ì •ì´ ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. 고장 대체 수수료가 비활성화 ìƒíƒœìž…니다. 몇 블ë¡ì„ 기다리거나 -fallbackfee를 활성화 하십시오.</translation>
</message>
<message>
+ <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">%s 파ì¼ì´ ì´ë¯¸ 존재합니다. ë¬´ì—‡ì„ í•˜ê³ ìž í•˜ëŠ”ì§€ 확실하시다면, 파ì¼ì„ 먼저 다른 곳으로 옮기십시오.</translation>
+ </message>
+ <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation type="unfinished">유효하지 ì•Šì€ ê¸ˆì•¡ -maxtxfee=&lt;amount&gt;: '%s' (거래가 막히는 ìƒí™©ì„ 방지하게 위해 ì ì–´ë„ %s ì˜ ì¤‘ê³„ 수수료를 지정해야 합니다)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">유효하지 않거나 ì†ìƒëœ peers.dat(%s). 만약 ì´ê²Œ ë²„ê·¸ì¸ ê²½ìš°ì—, %sì´ìª½ìœ¼ë¡œ 리í¬íŠ¸í•´ì£¼ì„¸ìš”. 새로 만들어서 시작하기 위한 해결방법으로 %s파ì¼ì„ 옮길 수 있습니다. (ì´ë¦„ 재설정, íŒŒì¼ ì˜®ê¸°ê¸° í˜¹ì€ ì‚­ì œ).</translation>
+ </message>
+ <message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
<translation type="unfinished">하나 ì´ìƒì˜ 양파 ë°”ì¸ë”© 주소가 제공ë©ë‹ˆë‹¤. ìžë™ìœ¼ë¡œ ìƒì„± ëœ Tor onion ì„œë¹„ìŠ¤ì— %s 사용.</translation>
</message>
<message>
+ <source>No dump file provided. To use createfromdump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">ë¤í”„파ì¼ì´ ìž…ë ¥ë˜ì§€ 않았습니다. ë¤í”„파ì¼ì„ 사용하기 위해서는 -dumpfile=&lt;filename&gt;ì´ ë°˜ë“œì‹œ ìž…ë ¥ë˜ì–´ì•¼ 합니다. </translation>
+ </message>
+ <message>
+ <source>No dump file provided. To use dump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">ë¤í”„파ì¼ì´ ìž…ë ¥ë˜ì§€ 않았습니다. ë¤í”„를 사용하기 위해서는 -dumpfile=&lt;filename&gt;ì´ ë°˜ë“œì‹œ ìž…ë ¥ë˜ì–´ì•¼ 합니다.</translation>
+ </message>
+ <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation type="unfinished">ì»´í“¨í„°ì˜ ë‚ ì§œì™€ ì‹œê°„ì´ ì˜¬ë°”ë¥¸ì§€ 확ì¸í•˜ì‹­ì‹œì˜¤! ì‹œê°„ì´ ìž˜ëª»ë˜ë©´ %sì€ ì œëŒ€ë¡œ ë™ìž‘하지 않습니다.</translation>
</message>
@@ -576,7 +630,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Done loading</source>
- <translation type="unfinished">로딩 완료</translation>
+ <translation type="unfinished">불러오기 완료</translation>
+ </message>
+ <message>
+ <source>Dump file %s does not exist.</source>
+ <translation type="unfinished">íŒŒì¼ ë²„ë¦¬ê¸° 1%s 존재 안함
+</translation>
+ </message>
+ <message>
+ <source>Error creating %s</source>
+ <translation type="unfinished">만들기 오류 1%s
+</translation>
</message>
<message>
<source>Error initializing block database</source>
@@ -592,7 +656,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Error loading %s: Private keys can only be disabled during creation</source>
- <translation type="unfinished">%s 로딩 실패: ê°œì¸í‚¤ëŠ” ìƒì„±í• ë•Œë§Œ 비활성화 í•  수 있습니다</translation>
+ <translation type="unfinished">%s 불러오기 오류: ê°œì¸í‚¤ëŠ” ìƒì„±í• ë•Œë§Œ 비활성화 í•  수 있습니다</translation>
</message>
<message>
<source>Error loading %s: Wallet corrupted</source>
@@ -612,11 +676,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Error reading from database, shutting down.</source>
- <translation type="unfinished">ë¸”ë¡ ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ë¶ˆëŸ¬ì˜¤ëŠ”ë° ì˜¤ë¥˜ê°€ ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤, 곧 종료ë©ë‹ˆë‹¤.</translation>
+ <translation type="unfinished">ë°ì´í„°ë² ì´ìŠ¤ë¥¼ ë¶ˆëŸ¬ì˜¤ëŠ”ë° ì˜¤ë¥˜ê°€ ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤, 곧 종료ë©ë‹ˆë‹¤.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">ì²´ì¸ ìƒíƒœ ë°ì´í„°ë² ì´ìŠ¤ 업그레ì´ë“œ 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤.</translation>
+ <source>Error reading next record from wallet database</source>
+ <translation type="unfinished">지갑 ë°ì´í„°ë² ì´ìŠ¤ì—ì„œ ë‹¤ìŒ ê¸°ë¡ì„ ë¶ˆëŸ¬ì˜¤ëŠ”ë° ì˜¤ë¥˜ê°€ ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤.</translation>
</message>
<message>
<source>Error: Disk space is low for %s</source>
@@ -627,6 +691,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">오류: í‚¤í’€ì´ ë°”ë‹¥ë‚¨, 키풀 ë¦¬í•„ì„ ë¨¼ì € 호출할 하십시오</translation>
</message>
<message>
+ <source>Error: Missing checksum</source>
+ <translation type="unfinished">오류: ì²´í¬ì„¬ 누ë½</translation>
+ </message>
+ <message>
+ <source>Error: Unable to write record to new wallet</source>
+ <translation type="unfinished">오류: 새로운 ì§€ê°‘ì— ê¸°ë¡í•˜ì§€ 못했습니다.</translation>
+ </message>
+ <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">í¬íŠ¸ ì—°ê²°ì— ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤. 필요하다면 -리슨=0 ì˜µì…˜ì„ ì‚¬ìš©í•˜ì‹­ì‹œì˜¤.</translation>
</message>
@@ -711,10 +783,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">-whitebind: '%s' 를 ì´ìš©í•˜ì—¬ í¬íŠ¸ë¥¼ 지정해야 합니다</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">프ë¡ì‹œ 서버가 지정ë˜ì§€ 않았습니다. -proxy =&lt;ip&gt; ë˜ëŠ” -proxy =&lt;ip:port&gt;를 사용하십시오.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">íŒŒì¼ ë””ìŠ¤í¬ë¦½í„°ê°€ 부족합니다.</translation>
</message>
@@ -723,10 +791,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ë¸”ë¡ ì¶•ì†ŒëŠ” ìŒìˆ˜ë¡œ 설정할 수 없습니다.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">ë¸”ë¡ ì¶•ì†Œ 모드는 -coinstatsindex와 호환ë˜ì§€ 않습니다.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">ë¸”ë¡ ì¶•ì†Œ 모드는 -txindex와 호환ë˜ì§€ 않습니다.</translation>
</message>
@@ -851,6 +915,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">키 ìƒì„± 불가</translation>
</message>
<message>
+ <source>Unable to open %s for writing</source>
+ <translation type="unfinished">%sì„ ì“°ê¸° 위하여 ì—´ 수 없습니다.</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">HTTP 서버를 시작할 수 없습니다. ìžì„¸í•œ ì‚¬í•­ì€ ë””ë²„ê·¸ 로그를 í™•ì¸ í•˜ì„¸ìš”.</translation>
</message>
@@ -867,12 +935,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">-onlynet: '%s' ì— ì•Œìˆ˜ì—†ëŠ” 네트워í¬ê°€ 지정ë˜ì—ˆìŠµë‹ˆë‹¤</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">지ì›ë˜ì§€ 않는 로깅 카테고리 %s = %s.</translation>
+ <source>Unknown new rules activated (versionbit %i)</source>
+ <translation type="unfinished">ì•Œ 수 없는 새로운 ê·œì¹™ì´ í™œì„±í™” ë˜ì—ˆìŠµë‹ˆë‹¤. (versionbit %i)</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">UTXO ë°ì´í„°ë² ì´ìŠ¤ 업그레ì´ë“œ</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">지ì›ë˜ì§€ 않는 로깅 카테고리 %s = %s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -1093,7 +1161,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n블ë¡ì˜ 트랜잭션 ë‚´ì—­ì´ ì²˜ë¦¬ë˜ì—ˆìŠµë‹ˆë‹¤.</numerusform>
</translation>
</message>
<message>
@@ -1129,10 +1197,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">최신 정보</translation>
</message>
<message>
+ <source>Ctrl+Q</source>
+ <translation type="unfinished">Crtl + Q</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction</source>
<translation type="unfinished">부분ì ìœ¼ë¡œ ì„œëª…ëœ ë¹„íŠ¸ì½”ì¸ íŠ¸ëžœìž­ì…˜ 불러오기</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">PSBT í˜¹ì€ í´ë¦½ë³´ë“œì—ì„œ 불러오기</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">í´ë¦½ë³´ë“œë¡œë¶€í„° 부분ì ìœ¼ë¡œ ì„œëª…ëœ ë¹„íŠ¸ì½”ì¸ íŠ¸ëžœìž­ì…˜ 불러오기</translation>
</message>
@@ -1169,6 +1245,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">지갑 닫기</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">지갑 복구</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">백업파ì¼ì—ì„œ 지갑 복구하기</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">모든 지갑 닫기</translation>
</message>
@@ -1193,6 +1279,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">사용 가능한 블ë¡ì´ 없습니다.</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">지갑 정보</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">지갑 ì´ë¦„</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">ì°½(&amp;W)</translation>
</message>
@@ -1212,6 +1308,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>&amp;Hide</source>
<translation type="unfinished">&amp;숨기기</translation>
</message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">보여주기</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1410,6 +1510,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">복사 &amp; 금액</translation>
</message>
<message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">거래 &amp; ê²°ê³¼ ì¸ë±ìŠ¤ê°’ í˜¹ì€ ID 복사</translation>
+ </message>
+ <message>
<source>L&amp;ock unspent</source>
<translation type="unfinished">L&amp;ock 미사용</translation>
</message>
@@ -1498,6 +1602,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">서명ìžë¥¼ 나열할 수 없습니다.</translation>
</message>
+ </context>
+<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">지갑 불러오기</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">지갑 불러오는 중...</translation>
+ </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1703,13 +1820,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Bitcoin</source>
<translation type="unfinished">비트코ì¸</translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(필요한 %1GB 중)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(ì „ì²´ ì²´ì¸ì— 필요한 %1GB)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1755,10 +1882,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">í”„ë¡œê·¸ëž¨ì´ ì²˜ìŒìœ¼ë¡œ 실행ë˜ê³  있습니다. %1ê°€ ì–´ë””ì— ë°ì´í„°ë¥¼ 저장할지 ì„ íƒí•  수 있습니다.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">'확ì¸'ì„ í´ë¦­í•˜ë©´, %1ì€ ëª¨ë“  %4 ë¸”ë¡ ì²´ì¸ (%2GB) 장부를 가장 최근 거래 부터 %3 ì•ˆì— ë‹¤ìš´ë¡œë“œí•˜ê³  처리하는ë°, ì´ê²ƒì€ %4ê°€ 활성화 ë ë•Œ 시작ë©ë‹ˆë‹¤. </translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">블ë¡ì²´ì¸ 스토리지를 다ìŒìœ¼ë¡œ 제한하기 </translation>
</message>
@@ -1867,7 +1990,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">ì•Œ 수 ì—†ìŒ. í—¤ë” ë™ê¸°í™” 중(%1, %2)...</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -1951,14 +2074,44 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ì´ ì„¤ì •ì„ ë˜ëŒë¦¬ë ¤ë©´ 처ìŒë¶€í„° 블ë¡ì²´ì¸ì„ 다시 다운로드 받아야 합니다.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">최대 ë°ì´í„°ë² ì´ìŠ¤ ìºì‹œ 사ì´ì¦ˆì— ë„달했습니다. ë” í° ìš©ëŸ‰ì˜ ìºì‹œëŠ” ë” ë¹ ë¥´ê²Œ 싱í¬ë¥¼ 맞출 수 있으며 ëŒ€ë¶€ë¶„ì˜ ìœ ì € ê²½ìš°ì— ìœ ë¦¬í•©ë‹ˆë‹¤. ìºì‹œ 사ì´ì¦ˆë¥¼ 작게 만드는 ê²ƒì€ ë©”ëª¨ë¦¬ ì‚¬ìš©ì„ ì¤„ìž…ë‹ˆë‹¤. 미사용 ë©¤í’€ì˜ ë©”ëª¨ë¦¬ëŠ” ì´ ìºì‹œë¥¼ 위해 공유ë©ë‹ˆë‹¤.</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">스í¬ë¦½íŠ¸ ê²€ì¦ ìˆ˜ëª…ì˜ ìˆ«ìžë¥¼ 설정하세요. ìŒìˆ˜ëŠ” ì‹œìŠ¤í…œì— ë¬¶ì´ì§€ 않는 ìžìœ ë¡œìš´ ì½”ì–´ì˜ ìˆ˜ë¥¼ 뜻합니다.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = ìžë™, &lt;0 = ì§€ì •ëœ ì½”ì–´ ê°œìˆ˜ë§Œí¼ ì‚¬ìš© 안함)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">당신 í˜¹ì€ 3ìžì˜ ê°œë°œíˆ´ì´ JSON-RPC 명령과 커맨드ë¼ì¸ì„ 통해 노드와 소통하는 ê²ƒì„ í—ˆë½í•©ë‹ˆë‹¤.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">R&amp;PC 서버를 가능하게 합니다.</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">지갑(&amp;A)</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">수수료 ê°ë©´ì„ 초기값으로 할지 í˜¹ì€ ì„¤ì •í•˜ì§€ ì•Šì„지를 결정합니다.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">초기 설정값으로 수수료를 ëºë‹ˆë‹¤.</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">전문가</translation>
</message>
@@ -1975,10 +2128,25 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ê²€ì¦ë˜ì§€ ì•Šì€ ìž”ëˆ ì“°ê¸° (&amp;S)</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">PSBT ì»¨íŠ¸ë¡¤ì„ ê°€ëŠ¥í•˜ê²Œ 합니다.</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">PSBT ì»¨íŠ¸ë¡¤ì„ ë³´ì—¬ì¤„ì§€ë¥¼ 결정합니다.</translation>
+ </message>
+ <message>
<source>External Signer (e.g. hardware wallet)</source>
<translation type="unfinished">외부 ì„œëª…ìž (예: 하드웨어 지갑)</translation>
</message>
<message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">외부 ì„œëª…ìž ìŠ¤í¬ë¦½íŠ¸ 경로
+ </translation>
+ </message>
+ <message>
<source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
<translation type="unfinished">ë¹„íŠ¸ì½”ì¸ ì½”ì–´ 호환 스í¬ë¦½íŠ¸ì˜ ì „ì²´ 경로 (예: C:\Downloads\whi.exe ë˜ëŠ” /Users/you/Downloads/hwi.py). 주ì˜: 악성 í”„ë¡œê·¸ëž¨ì´ ì½”ì¸ì„ 훔칠 수 있습니다!</translation>
</message>
@@ -2075,6 +2243,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ì¸í„°íŽ˜ì´ìŠ¤ì— 표시하고 ì½”ì¸ì„ 보낼때 사용할 기본 최소화 단위를 ì„ íƒí•˜ì‹­ì‹œì˜¤.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">ë‚´ìš© 메뉴 ì•„ì´í…œìœ¼ë¡œ 거래내역 íƒ­ì´ ë³´ì´ëŠ” ì œ3ìž URL (블ë¡ìµìŠ¤í”„로러). URLì— %s는 트랜잭션 해시값으로 대체ë©ë‹ˆë‹¤. ë³µìˆ˜ì˜ URLì€ ìˆ˜ì§í•­ëª©ìœ¼ë¡œë¶€í„° 분리ë©ë‹ˆë‹¤. </translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">ì œ3ìž íŠ¸ëžœìž­ì…˜ URL</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">ì½”ì¸ ìƒì„¸ ì œì–´ê¸°ëŠ¥ì— ëŒ€í•œ 표시 여부를 ì„ íƒí•  수 있습니다.</translation>
</message>
@@ -2095,8 +2271,8 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1 í¬í•¨ë¨</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">ì´ ë‹¤ì´ì–¼ë¡œê·¸ì—ì„œ 설정한 ì˜µì…˜ì€ ì»¤ë§¨ë“œë¼ì¸ì´ë‚˜ 설정파ì¼ì— ì˜í•´ 바뀔 수 있습니다:</translation>
+ <source>closest matching "%1"</source>
+ <translation type="unfinished">가장 가까운 ì˜ë¯¸ "1%1"</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -2121,14 +2297,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">옵션 초기화를 확실화하기</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">변경 ì‚¬í•­ì„ ì ìš©í•˜ê¸° 위해서는 í”„ë¡œê·¸ëž¨ì´ ì¢…ë£Œ 후 재시작ë˜ì–´ì•¼ 합니다.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">í´ë¼ì´ì–¸íŠ¸ê°€ 종료ë©ë‹ˆë‹¤, ê³„ì† ì§„í–‰í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
</message>
<message>
@@ -2280,8 +2459,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">거래 서명 실패: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">ì§€ê°‘ì´ ìž ê²¨ìžˆëŠ” ë™ì•ˆ ìž…ë ¥ì„ ì„œëª…í•  수 없습니다.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
- <translation type="unfinished">ë” ì´ìƒ 추가ì ì¸ ì¸í’‹ì— 대해 서명할 수 ì—†ìŒ</translation>
+ <translation type="unfinished">ë” ì´ìƒ 추가ì ì¸ ìž…ë ¥ì— ëŒ€í•´ 서명할 수 없습니다.</translation>
</message>
<message>
<source>Signed transaction successfully. Transaction is ready to broadcast.</source>
@@ -2349,6 +2532,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">거래가 ì•„ì§ ì„œëª…(들)ì„ í•„ìš”ë¡œ 합니다.</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">하지만 지갑 ë¡œë”©ì´ ë˜ì§€ 않았습니다.</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(그러나 ì´ ì§€ê°‘ì€ ê±°ëž˜ì— ì„œëª…ì´ ë¶ˆê°€ëŠ¥í•©ë‹ˆë‹¤.)</translation>
</message>
@@ -2609,6 +2796,26 @@ BIP70ì˜ ê´‘ë²”ìœ„í•œ 보안 결함으로 ì¸í•´ 모든 가맹ì ì—서는 지ê°
<translation type="unfinished">ë§¤í•‘ëœ AS</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">ì´ í”¼ì–´ì—게 지갑주소를 릴레ì´í• ì§€ë¥¼ 결정합니다.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">지갑주소를 릴레ì´í•©ë‹ˆë‹¤.</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">ì²˜ë¦¬ëœ ì§€ê°‘</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">ì§€ê°‘ì˜ Rate제한</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">유저 ì—ì´ì „트</translation>
</message>
@@ -2746,6 +2953,37 @@ BIP70ì˜ ê´‘ë²”ìœ„í•œ 보안 결함으로 ì¸í•´ 모든 가맹ì ì—서는 지ê°
<translation type="unfinished">출력:</translation>
</message>
<message>
+ <source>Inbound: initiated by peer</source>
+ <extracomment>Explanatory text for an inbound peer connection.</extracomment>
+ <translation type="unfinished">ì‹œìž‘ì  : ë™ê¸°ì— ì˜í•´ 시작ë¨</translation>
+ </message>
+ <message>
+ <source>Outbound Full Relay: default</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</extracomment>
+ <translation type="unfinished">아웃바운드 ì „ì²´ 릴레ì´: 기본값</translation>
+ </message>
+ <message>
+ <source>Outbound Block Relay: does not relay transactions or addresses</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">아웃바운드 ë¸”ë¡ ë¦´ë ˆì´: 트랜잭션 ë˜ëŠ” 주소를 릴레ì´í•˜ì§€ ì•ŠìŒ</translation>
+ </message>
+ <message>
+ <source>Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">아웃바운드 매뉴얼 : RPC 1%1 ì´ë‚˜ 2%2/3%3 ì„ ì‚¬ìš©í•´ì„œ 환경설정 ì˜µì…˜ì„ ì¶”ê°€</translation>
+ </message>
+ <message>
+ <source>Outbound Feeler: short-lived, for testing addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Outbound Feeler: ì§§ì€ ìš©ë„, 주소 테스트용</translation>
+ </message>
+ <message>
+ <source>Outbound Address Fetch: short-lived, for soliciting addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</extracomment>
+ <translation type="unfinished">아웃바운드 주소 가져오기: 단기, 주소 요청용
+ </translation>
+ </message>
+ <message>
<source>we selected the peer for high bandwidth relay</source>
<translation type="unfinished">ì €í¬ëŠ” 가장 빠른 대역í­ì„ 가지고 있는 피어를 ì„ íƒí•©ë‹ˆë‹¤.</translation>
</message>
@@ -2754,6 +2992,10 @@ BIP70ì˜ ê´‘ë²”ìœ„í•œ 보안 결함으로 ì¸í•´ 모든 가맹ì ì—서는 지ê°
<translation type="unfinished">피어는 ë†’ì€ ëŒ€ì—­í­ì„ 위해 우리를 ì„ íƒí•©ë‹ˆë‹¤</translation>
</message>
<message>
+ <source>no high bandwidth relay selected</source>
+ <translation type="unfinished">ê³ ëŒ€ì—­í­ ë¦´ë ˆì´ê°€ ì„ íƒë˜ì§€ ì•ŠìŒ</translation>
+ </message>
+ <message>
<source>&amp;Copy address</source>
<extracomment>Context menu action to copy the address of a peer.</extracomment>
<translation type="unfinished">&amp; 주소 복사</translation>
@@ -2779,6 +3021,11 @@ BIP70ì˜ ê´‘ë²”ìœ„í•œ 보안 결함으로 ì¸í•´ 모든 가맹ì ì—서는 지ê°
<translation type="unfinished">1ë…„(&amp;Y)</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">IP/Netmask 복사하기</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">노드 차단 취소(&amp;U)</translation>
</message>
@@ -2795,6 +3042,23 @@ BIP70ì˜ ê´‘ë²”ìœ„í•œ 보안 결함으로 ì¸í•´ 모든 가맹ì ì—서는 지ê°
<translation type="unfinished">"%1" ì§€ê°‘ì„ ì‚¬ìš©í•˜ì—¬ 명령 실행</translation>
</message>
<message>
+ <source>Welcome to the %1 RPC console.
+Use up and down arrows to navigate history, and %2 to clear screen.
+Use %3 and %4 to increase or decrease the font size.
+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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">1%1 RPC ì½˜ì†”ì— ì˜¤ì‹  ê²ƒì„ í™˜ì˜í•©ë‹ˆë‹¤.
+위쪽 ë° ì•„ëž˜ìª½ 화살표를 사용하여 ê¸°ë¡ íƒìƒ‰ì„하고 2%2를 사용하여 í™”ë©´ì„ ì§€ìš°ì„¸ìš”.
+3%3ê³¼ 4%4ì„ ì‚¬ìš©í•˜ì—¬ 글꼴 í¬ê¸° ì¦ê°€ ë˜ëŠ” ê°ì†Œí•˜ì„¸ìš”
+사용 가능한 ëª…ë ¹ì˜ ê°œìš”ë¥¼ 보려면 5%5를 입력하십시오.
+ì´ ì½˜ì†” ì‚¬ìš©ì— ëŒ€í•œ ìžì„¸í•œ ë‚´ìš©ì„ ë³´ë ¤ë©´ 6%6ì„ ìž…ë ¥í•˜ì‹­ì‹œì˜¤.
+7%7 경고: ì‚¬ê¸°ê¾¼ë“¤ì€ ì‚¬ìš©ìžë“¤ì—게 ì—¬ê¸°ì— ëª…ë ¹ì„ ìž…ë ¥í•˜ë¼ê³  ë§í•˜ê³  활발히 ê¸ˆí’ˆì„ í›”ì¹©ë‹ˆë‹¤. 완전히 ì´í•´í•˜ì§€ ì•Šê³  ì´ ì½˜ì†”ì„ ì‚¬ìš©í•˜ì§€ 마십시오. 8%8
+</translation>
+ </message>
+ <message>
<source>Executing…</source>
<extracomment>A console message indicating an entered command is currently being executed.</extracomment>
<translation type="unfinished">실행 중...</translation>
@@ -3242,6 +3506,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">%1ì„ %2ë¡œ</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details…"</source>
+ <translation type="unfinished">ìˆ˜ì‹ ìž ëª©ë¡ì„ 검토하기 위해 "ìžì„¸ížˆ 보기"를 í´ë¦­í•˜ì„¸ìš”</translation>
+ </message>
+ <message>
+ <source>Sign failed</source>
+ <translation type="unfinished">서명 실패</translation>
+ </message>
+ <message>
<source>External signer not found</source>
<extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
<translation type="unfinished">외부 서명ìžë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</translation>
@@ -3265,6 +3537,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">PSBT 저장ë¨</translation>
</message>
<message>
+ <source>External balance:</source>
+ <translation type="unfinished">ì™¸ë¶€ì˜ ìž”ê³ </translation>
+ </message>
+ <message>
<source>or</source>
<translation type="unfinished">ë˜ëŠ”</translation>
</message>
@@ -3278,6 +3554,16 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">거래 ì œì•ˆì„ ê²€í† í•´ 주십시오. ì´ê²ƒì€ ë‹¹ì‹ ì´ ì €ìž¥í•˜ê±°ë‚˜ 복사한 ë’¤ e.g. 오프ë¼ì¸ %1 지갑 ë˜ëŠ” PSBT 호환 하드웨어 지갑으로 서명할 수 있는 PSBT (부분ì ìœ¼ë¡œ ì„œëª…ëœ ë¹„íŠ¸ì½”ì¸ íŠ¸ëžœìž­ì…˜)를 ìƒì„±í•  것입니다.</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">ì´ íŠ¸ëžœìž­ì…˜ì„ ìƒì„±í•˜ê² ìŠµë‹ˆê¹Œ?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">ë‹¹ì‹ ì˜ íŠ¸ëžœìž­ì…˜ì„ ê²€í† í•˜ì„¸ìš”. ë‹¹ì‹ ì€ íŠ¸ëžœìž­ì…˜ì„ ìƒì„±í•˜ê³  보낼 수 있습니다. í˜¹ì€ ë¶€ë¶„ì ìœ¼ë¡œ ì„œëª…ëœ ë¹„íŠ¸ì½”ì¸ íŠ¸ëžœìž­ì…˜ (PSBT, Partially Signed Bitcoin Transaction)ì„ ìƒì„±í•˜ê³ , 저장하거나 복사하여 오프ë¼ì¸ %1지갑으로 ì„œëª…í• ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. PSBTê°€ ì ìš©ë˜ëŠ” 하드월렛으로 서명할 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. </translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">거래를 재검토 하십시오</translation>
@@ -3330,10 +3616,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">%1 보다 í° ìˆ˜ìˆ˜ë£ŒëŠ” 지나치게 ë†’ì€ ìˆ˜ìˆ˜ë£Œ 입니다.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">지불 ìš”ì²­ì´ ë§Œë£Œë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3412,14 +3694,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">메시지:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">ì¸ì¦ ë˜ì§€ ì•Šì€ ì§€ë¶ˆ 요청입니다.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">ì¸ì¦ ëœ ì§€ë¶ˆ 요청 입니다.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">ì´ ì£¼ì†Œì— ë¼ë²¨ì„ 입력하면 ì‚¬ìš©ëœ ì£¼ì†Œ 목ë¡ì— ë¼ë²¨ì´ 표시ë©ë‹ˆë‹¤</translation>
</message>
@@ -3427,14 +3701,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">bitcoin: URIì— ì¶”ê°€ëœ ë©”ì‹œì§€ëŠ” 참고를 위해 거래내역과 함께 ì €ìž¥ë  ê²ƒìž…ë‹ˆë‹¤. Note: ì´ ë©”ì‹œì§€ëŠ” ë¹„íŠ¸ì½”ì¸ ë„¤íŠ¸ì›Œí¬ë¡œ 전송ë˜ì§€ 않습니다.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">보낼 주소:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">메모:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3591,33 +3857,36 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
</context>
<context>
- <name>TransactionDesc</name>
- <message>
- <source>conflicted with a transaction with %1 confirmations</source>
- <translation type="unfinished">%1 승ì¸ì´ 있는 거래와 충ëŒí•¨</translation>
- </message>
+ <name>SplashScreen</name>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/미승ì¸, %1</translation>
+ <source>(press q to shutdown and continue later)</source>
+ <translation type="unfinished">q 를 눌러 종료하거나 ë‚˜ì¤‘ì— ê³„ì†í•˜ì„¸ìš”.</translation>
</message>
<message>
- <source>in memory pool</source>
- <translation type="unfinished">메모리 í’€ ì•ˆì— ìžˆìŒ</translation>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">q를 눌러 종료하세요</translation>
</message>
+</context>
+<context>
+ <name>TransactionDesc</name>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">메모리 í’€ ì•ˆì— ì—†ìŒ</translation>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
+ <translation type="unfinished">%1 승ì¸ì´ 있는 거래와 충ëŒí•¨</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">버려진</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/미확ì¸</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 í™•ì¸ ì™„ë£Œ</translation>
</message>
<message>
@@ -3940,10 +4209,35 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">복사 트랜잭션 &amp; ì•„ì´ë””</translation>
</message>
<message>
+ <source>Copy &amp;raw transaction</source>
+ <translation type="unfinished">처리ë˜ì§€ ì•Šì€ íŠ¸ëžœìž­ì…˜ 복사</translation>
+ </message>
+ <message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">트랜잭션 전체와 ìƒì„¸ë‚´ì—­ 복사</translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">트랜잭션 ìƒì„¸ë‚´ì—­ 보여주기</translation>
+ </message>
+ <message>
+ <source>Increase transaction &amp;fee</source>
+ <translation type="unfinished">트랜잭션 수수료 올리기</translation>
+ </message>
+ <message>
+ <source>A&amp;bandon transaction</source>
+ <translation type="unfinished">트랜잭션 í기하기</translation>
+ </message>
+ <message>
<source>&amp;Edit address label</source>
<translation type="unfinished">&amp;주소 ë¼ë²¨ 수정하기</translation>
</message>
<message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">%1내로 보여주기</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">거래 ê¸°ë¡ ë‚´ë³´ë‚´ê¸°</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ku.ts b/src/qt/locale/bitcoin_ku.ts
new file mode 100644
index 0000000000..b41ab41d6a
--- /dev/null
+++ b/src/qt/locale/bitcoin_ku.ts
@@ -0,0 +1,357 @@
+<TS version="2.1" language="ku">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>&amp;New</source>
+ <translation type="unfinished">&amp;Nû</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation type="unfinished">&amp;Kopi bike</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation type="unfinished">Bigire</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">Navnîşana hilbijartî ji lîsteyê rake</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">Ji bo lêgerînê navnîşan an jî etîketê têkeve</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Daneya di hilpekîna niha de bi rêya dosyayekê derxîne</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">Derxîne</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">Jê bibe</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">Navnîşana ku ew ê koîn were şandin, hilbijêre</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">Navnîşana ku ew ê koînan bistîne, hilbijêre</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation type="unfinished">H&amp;ilbijêre</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation type="unfinished">Navnîşanên şandinê</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation type="unfinished">Navnîşanên stendinê</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation type="unfinished">&amp;Navnîşanê kopî bike</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">Etîketê &amp;kopî bike</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">&amp;Serrast bike</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation type="unfinished">Lîsteya navnîşanan derxîne</translation>
+ </message>
+ </context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Etîket</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">Navnîşan</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(etîket tune)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Enter passphrase</source>
+ <translation type="unfinished">Pêborîna xwe têkevê</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation type="unfinished">Pêborîna nû</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation type="unfinished">Pêborîna xwe ya nû dubare bike</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation type="unfinished">Pêborînê nîşan bide</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation type="unfinished">Şîfrekirina cizdên</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation type="unfinished">Kilîda cizdên veke</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation type="unfinished">Pêborînê biguherîne</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation type="unfinished">Şîfrekirina cizdên bipejirîne</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">Tu bi rastî jî dixwazî cizdanê xwe şîfre bikî?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">Cizdan hate şîfrekirin</translation>
+ </message>
+ </context>
+<context>
+ <name>QObject</name>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">Cizdan:</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation type="unfinished">Agahî</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Tarîx</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(etîket tune)</translation>
+ </message>
+ </context>
+<context>
+ <name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(sufficient to restore backups %n day(s) old)</source>
+ <extracomment>Explanatory text on the capability of the current prune target.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>Address</source>
+ <extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
+ <translation type="unfinished">Navnîşan</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <extracomment>Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</extracomment>
+ <translation type="unfinished">Cure</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">Cizdan:</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Tarîx</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Etîket</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(etîket tune)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(etîket tune)</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Tarîx</translation>
+ </message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Tarîx</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation type="unfinished">Cure</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Etîket</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(etîket tune)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Tarîx</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation type="unfinished">Cure</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Etîket</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">Navnîşan</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">Derxîne</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Daneya di hilpekîna niha de bi rêya dosyayekê derxîne</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_ku_IQ.ts b/src/qt/locale/bitcoin_ku_IQ.ts
index f78a465fbe..aebd62b774 100644
--- a/src/qt/locale/bitcoin_ku_IQ.ts
+++ b/src/qt/locale/bitcoin_ku_IQ.ts
@@ -137,6 +137,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">دووبارەکردنەوەی دەستەواژەی تێپەڕی نوێ</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation type="unfinished">نیشان دانا ناوه چونه</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation type="unfinished">کی٠خو یه پاره رمزه دانینه بر</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation type="unfinished">او شوله بو ور کرنا کی٠پاره گرکه رمزا Ú©ÛŒÙÙ‡ وؤ یه پاره بزانی</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">به راستی اون هشیارن کا دخازن بو کی٠خو یه پاره رمزه دانین</translation>
+ </message>
+ <message>
<source>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">دەستەواژەی تێپەڕەوی نوێ تێبنووسە بۆ جزدان.1 تکایە دەستەواژەی تێپەڕێک بەکاربێنە لە 2ten یان زیاتر لە هێما هەڕەمەکیەکان2، یان 38 یان زیاتر ووشەکان3.</translation>
</message>
@@ -240,6 +256,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinGUI</name>
<message>
+ <source>&amp;About %1</source>
+ <translation type="unfinished">&amp;دەربارەی %1</translation>
+ </message>
+ <message>
<source>&amp;Send</source>
<translation type="unfinished">&amp;ناردن</translation>
</message>
@@ -348,6 +368,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -368,10 +409,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">بەخێربێن</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">کاتێک کرتە لە پەسەندە دەکەیت، %1 دەست دەکات بە داگرتن و پرۆسەی زنجیرەبلۆکی %4 (%2GB) بە سەرەتاییترین مامەڵەکان لە %3 دەست پێدەکات کاتێک %4 لە سەرەتادا دەستی پێکرد.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">دووبارە کردنەوەی ئەم ڕێکخستنە پێویستی بە دووبارە داگرتنی تەواوی بەربەستەکە هەیە. خێراترە بۆ داگرتنی زنجیرەی تەواو سەرەتا و داگرتنی دواتر. هەندێک تایبەتمەندی پێشکەوتوو لە کار دەهێنێت.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ky.ts b/src/qt/locale/bitcoin_ky.ts
index db2ee8975c..80320eccb0 100644
--- a/src/qt/locale/bitcoin_ky.ts
+++ b/src/qt/locale/bitcoin_ky.ts
@@ -144,6 +144,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts
index b595e3e706..49b7d4c1e2 100644
--- a/src/qt/locale/bitcoin_la.ts
+++ b/src/qt/locale/bitcoin_la.ts
@@ -521,6 +521,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -647,6 +668,7 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirma optionum reconstituere</translation>
</message>
<message>
@@ -933,10 +955,6 @@
<source>Message:</source>
<translation type="unfinished">Nuntius:</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pensa Ad:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1053,10 +1071,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/non confirmata</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 confirmationes</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts
index 6d1d346a38..7d31d279f7 100644
--- a/src/qt/locale/bitcoin_lt.ts
+++ b/src/qt/locale/bitcoin_lt.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">Spustelėkite dešinįjį klavišą norint keisti adresą arba etiketę</translation>
+ <translation type="unfinished">Spustelėkite dešinįjį pelės klavišą norint keisti adresą arba etiketę </translation>
</message>
<message>
<source>Create a new address</source>
@@ -70,6 +70,12 @@
<translation type="unfinished">Tai yra jÅ«sų Bitcoin adresai iÅ¡einantiems mokÄ—jimams. Visada pasitikrinkite sumÄ… ir gavÄ—jo adresÄ… prieÅ¡ siunÄiant lÄ—Å¡as.</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Tai jūsų Bitcoin mokėjimų gavimo adresai. Naudokite 'Sukurti naują gavimo adresą' mygtuką gavimų skirtuke kad sukurtumėte naujus adresus.
+Pasirašymas galimas tik su 'legacy' tipo adresais.</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">&amp;Kopijuoti adresÄ…</translation>
</message>
@@ -86,6 +92,11 @@
<translation type="unfinished">Eksportuoti adresų sąrašą</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Kableliais atskirtas failas</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">Bandant išsaugoti adresų sąrašą - įvyko klaida keliant į %1. Prašome bandyti dar kartą.</translation>
@@ -190,7 +201,7 @@
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation type="unfinished">Dėl vidinės klaidos nepavyko užšifruoti piniginę.Piniginė neužšifruota.</translation>
+ <translation type="unfinished">Dėl vidinės klaidos nepavyko užšifruoti piniginę. Piniginė neužšifruota.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
@@ -227,6 +238,10 @@
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Nustatymų failas %1 galimai sugadintas arba klaidingas</translation>
+ </message>
+ <message>
<source>Internal error</source>
<translation type="unfinished">VidinÄ— klaida</translation>
</message>
@@ -246,6 +261,10 @@
<translation type="unfinished">Klaida: %1</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 dar saugiai neužbaigė darbo...</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation type="unfinished">nežinomas</translation>
</message>
@@ -340,6 +359,14 @@
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Nustatymų failas negalėjo būti perskaitytas</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Nustatymų failas negalėjo būti parašytas</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">%s kūrėjai</translation>
</message>
@@ -476,10 +503,6 @@
<translation type="unfinished">Nežinomas adreso tipas '%s'</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">UTXO duomenų bazės atnaujinimas</translation>
- </message>
- <message>
<source>Verifying blocks…</source>
<translation type="unfinished">Tikrinami blokai...</translation>
</message>
@@ -539,6 +562,10 @@
<translation type="unfinished">Sukurti naujÄ… piniginÄ™</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Sumažinti</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">PiniginÄ—</translation>
</message>
@@ -572,6 +599,10 @@
<translation type="unfinished">&amp;Gauti</translation>
</message>
<message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;Nustatymai</translation>
+ </message>
+ <message>
<source>Encrypt the private keys that belong to your wallet</source>
<translation type="unfinished">Užšifruoti privaÄius raktus, kurie priklauso jÅ«sų piniginei</translation>
</message>
@@ -700,6 +731,11 @@
<translation type="unfinished">Piniginių nėra</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">PiniginÄ—s Pavadinimas</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Langas</translation>
</message>
@@ -1129,6 +1165,30 @@
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Šiame kataloge bus saugomi bent %1 GB duomenų, kurie laikui bėgant didės.</translation>
@@ -1175,10 +1235,6 @@
<translation type="unfinished">Kadangi tai yra pirmas kartas, kai programa paleidžiama, galite pasirinkti, kur %1 išsaugos savo duomenis.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Spustelėjus Gerai, %1 pradės atsisiųsti ir apdoroti visą %4 blokų grandinę (%2GB), pradedant nuo ankstesnių operacijų %3, kai iš pradžių buvo paleista %4.</translation>
- </message>
- <message>
<source> GB</source>
<translation type="unfinished">GB</translation>
</message>
@@ -1447,10 +1503,6 @@
<translation type="unfinished">Rodyti monetų valdymo funkcijas, ar ne.</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Šiame dialogo lange nustatytos parinktys yra panaikintos komandų eilutėje arba konfigūracijos faile:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;Gerai</translation>
</message>
@@ -1468,14 +1520,17 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Patvirtinti nustatymų atstatymą</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Kliento perkrovimas reikalingas nustatymų aktyvavimui</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Klientas bus uždarytas. Ar norite testi?</translation>
</message>
<message>
@@ -2333,10 +2388,6 @@
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Mokestis, didesnis nei %1, laikomas absurdiÅ¡kai aukÅ¡tu mokesÄiu.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Mokėjimo prašymas pasibaigė</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2413,14 +2464,6 @@
<translation type="unfinished">Žinutė:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Tai yra nepatvirtinta mokėjimo užklausos suma</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Tai yra patvirtintas mokėjimo prašymas.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Įveskite šio adreso etiketę, kad ją pridėtumėte prie naudojamų adresų sąrašo</translation>
</message>
@@ -2428,14 +2471,6 @@
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Pranešimas, kuris buvo pridėtas prie bitcoin: URI, kuris bus saugomas kartu su sandoriu jūsų nuoroda. Pastaba: šis pranešimas nebus išsiųstas per „Bitcoin“ tinklą.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">MokÄ—ti gavÄ—jui:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">AtmintinÄ—:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -2571,30 +2606,22 @@
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">prieštaravo sandoriui su %1 patvirtinimais</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/nepatvirtintas, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">atminties talpykloje</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ne atminties talpykloje</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">paliktas</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/nepatvirtintas</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 patvirtinimų</translation>
</message>
<message>
@@ -2883,6 +2910,11 @@
<translation type="unfinished">Eksportuoti sandorių istoriją</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Kableliais atskirtas failas</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">Patvirtinta</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lv.ts b/src/qt/locale/bitcoin_lv.ts
index 972fa659f8..9497005299 100644
--- a/src/qt/locale/bitcoin_lv.ts
+++ b/src/qt/locale/bitcoin_lv.ts
@@ -88,7 +88,7 @@
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
- <translation type="unfinished">MÄ“Ä£inot saglabÄt adreÅ¡u sarakstu %1 radÄs kļūda. MÄ“Ä£iniet vÄ“lreiz.</translation>
+ <translation type="unfinished">MÄ“Ä£inot saglabÄt adreÅ¡u sarakstu %1 radÄs kļūda. LÅ«dzu mÄ“Ä£iniet vÄ“lreiz.</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -126,7 +126,7 @@
</message>
<message>
<source>Repeat new passphrase</source>
- <translation type="unfinished">JaunÄ parole vÄ“lreiz</translation>
+ <translation type="unfinished">Ievadiet jauno paroli vēlreiz</translation>
</message>
<message>
<source>Show passphrase</source>
@@ -185,10 +185,18 @@
<translation type="unfinished">Maciņa Å¡ifrÄ“Å¡ana neizdevÄs</translation>
</message>
<message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">IevadÄ«tÄs paroles nav vienÄdas.</translation>
+ </message>
+ <message>
<source>Wallet unlock failed</source>
<translation type="unfinished">Maciņa atslÄ“gÅ¡ana neizdevÄs</translation>
</message>
- </context>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished">Uzmanību! Caps Lock uz klavietūras ir ieslēgts!</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
@@ -318,6 +326,10 @@
<translation type="unfinished">&amp;Par %1</translation>
</message>
<message>
+ <source>Show information about %1</source>
+ <translation type="unfinished">RÄdÄ«t informÄciju par %1</translation>
+ </message>
+ <message>
<source>About &amp;Qt</source>
<translation type="unfinished">Par &amp;Qt</translation>
</message>
@@ -326,6 +338,10 @@
<translation type="unfinished">ParÄdÄ«t informÄciju par Qt</translation>
</message>
<message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Izveidot jaunu maciņu</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Maciņš:</translation>
</message>
@@ -350,6 +366,10 @@
<translation type="unfinished">&amp;Saņemt</translation>
</message>
<message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;Opcijas...</translation>
+ </message>
+ <message>
<source>Encrypt the private keys that belong to your wallet</source>
<translation type="unfinished">Å ifrÄ“t privÄtÄs atslÄ“gas kuras pieder tavam maciņam</translation>
</message>
@@ -378,6 +398,10 @@
<translation type="unfinished">Ciļņu rīkjosla</translation>
</message>
<message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Sinhronizē ar tīklu</translation>
+ </message>
+ <message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished">PieprasÄ«t maksÄjumus (izveido QR kodu un bitcoin: URIs)</translation>
</message>
@@ -550,6 +574,30 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -740,9 +788,15 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">ApstiprinÄt iestatÄ«jumu atiestatÄ«Å¡anu</translation>
</message>
<message>
+ <source>Configuration options</source>
+ <extracomment>Window title text of pop-up box that allows opening up of configuration file.</extracomment>
+ <translation type="unfinished">KonfigurÄciju Opcijas</translation>
+ </message>
+ <message>
<source>Error</source>
<translation type="unfinished">Kļūda</translation>
</message>
@@ -789,6 +843,33 @@
<source>Your current total balance</source>
<translation type="unfinished">JÅ«su kopÄ“jÄ tekoÅ¡Ä bilance</translation>
</message>
+ <message>
+ <source>Spendable:</source>
+ <translation type="unfinished">Iztērējams:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation type="unfinished">NesenÄs transakcijas</translation>
+ </message>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation type="unfinished">Dialogs</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation type="unfinished">Nokopēt</translation>
+ </message>
+ <message>
+ <source>Save…</source>
+ <translation type="unfinished">SaglabÄt...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation type="unfinished">Aiztaisīt</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
@@ -1084,10 +1165,6 @@
<source>Message:</source>
<translation type="unfinished">Ziņojums:</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">MaksÄt:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1223,6 +1300,10 @@
<context>
<name>WalletFrame</name>
<message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Izveidot jaunu maciņu</translation>
+ </message>
+ <message>
<source>Error</source>
<translation type="unfinished">Kļūda</translation>
</message>
diff --git a/src/qt/locale/bitcoin_mk.ts b/src/qt/locale/bitcoin_mk.ts
index 9c428ee03a..8558fe17ba 100644
--- a/src/qt/locale/bitcoin_mk.ts
+++ b/src/qt/locale/bitcoin_mk.ts
@@ -341,6 +341,30 @@
<translation type="unfinished">Биткоин</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_ml.ts b/src/qt/locale/bitcoin_ml.ts
index c0294c8a08..16456cfc86 100644
--- a/src/qt/locale/bitcoin_ml.ts
+++ b/src/qt/locale/bitcoin_ml.ts
@@ -317,10 +317,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ഡാറàµà´±à´¾à´¬àµ‡à´¸à´¿àµ½ നിനàµà´¨àµà´‚ വായിചàµà´šàµ†à´Ÿàµà´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ തടസം നേരിടàµà´Ÿàµ, à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´‚ അവസാനിപàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">ചെയിൻസàµà´±àµà´±àµ‡à´±àµà´±àµ ഡാറàµà´±à´¾à´¬àµ‡à´¸àµ à´…à´ªàµà´—àµà´°àµ‡à´¡àµ ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿àµ½ തടസം നേരിടàµà´Ÿàµ</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Error: %s ൽ à´¡à´¿à´¸àµà´•àµ à´¸àµà´ªàµ‡à´¸àµ വളരെ à´•àµà´±à´µà´¾à´£àµ</translation>
</message>
@@ -624,6 +620,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">വാലറàµà´±àµ à´’à´¨àµà´¨àµà´‚ ലഭàµà´¯à´‚ à´…à´²àµà´² </translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">വാലറàµà´±àµ പേരàµ</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;ജാലകം </translation>
</message>
@@ -986,6 +987,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ബിറàµà´±àµà´•àµ‹à´¯à´¿àµ»</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -1234,10 +1256,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Copy change</source>
<translation type="unfinished">ചേഞàµà´šàµ പകർതàµà´¤àµ</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">പെയàµà´®àµ†à´¨àµà´±à´¿à´¨àµà´³àµà´³ à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¨ കാലഹരണപàµà´ªàµ†à´Ÿàµà´Ÿàµ പോയിരികàµà´•àµà´¨àµà´¨àµ. </translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -1272,6 +1290,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>TransactionDesc</name>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 à´¸àµà´¥à´¿à´°àµ€à´•à´°à´£à´™àµà´™àµ¾</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts
index ae0831c418..8e5bb08729 100644
--- a/src/qt/locale/bitcoin_mn.ts
+++ b/src/qt/locale/bitcoin_mn.ts
@@ -439,6 +439,27 @@
<translation type="unfinished">Биткойн</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -500,6 +521,7 @@
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Ѳѳрчлѳлтүүдийг идÑвхижүүлхийн тулд клиентийг ахин ÑхлүүлÑÑ… шаардлагтай</translation>
</message>
<message>
@@ -779,10 +801,6 @@
<source>Message:</source>
<translation type="unfinished">ЗурваÑ:</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Тѳлѳх хаÑг:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -799,10 +817,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/баталгаажаагүй</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 баталгаажилтууд</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_mr_IN.ts b/src/qt/locale/bitcoin_mr_IN.ts
index d06e977f93..2641e4586a 100644
--- a/src/qt/locale/bitcoin_mr_IN.ts
+++ b/src/qt/locale/bitcoin_mr_IN.ts
@@ -86,6 +86,11 @@
<translation type="unfinished">पतà¥à¤¤à¥à¤¯à¤¾à¤šà¥€ निरà¥à¤¯à¤¾à¤¤ करा</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">कॉमा सेपरेटेड फ़ाइल</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation type="unfinished">निरà¥à¤¯à¤¾à¤¤ अयशसà¥à¤µà¥€</translation>
</message>
@@ -106,7 +111,22 @@
</message>
</context>
<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">à¤à¤• गंभीर तà¥à¤°à¥à¤Ÿà¥€ आली. %1यापà¥à¤¢à¥‡ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤ªà¤£à¥‡ सà¥à¤°à¥‚ ठेवू शकत नाही आणि संपेल.</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">अंतरà¥à¤—त तà¥à¤°à¥à¤Ÿà¥€</translation>
+ </message>
+ </context>
+<context>
<name>QObject</name>
+ <message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1अजून सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤ªà¤£à¥‡ बाहेर पडलो नाही...</translation>
+ </message>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
@@ -151,7 +171,79 @@
</message>
</context>
<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">सेटिंगà¥à¤œ फाइल वाचता आली नाही</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">सेटिंगà¥à¤œ फाइल लिहिता आली नाही</translation>
+ </message>
+ </context>
+<context>
<name>BitcoinGUI</name>
+ <message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;मिनीमाइज़</translation>
+ </message>
+ <message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;परà¥à¤¯à¤¾à¤¯</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;à¤à¤¨à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ वॉलेट</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;बॅकअप वॉलेट…
+ </translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;पासफà¥à¤°à¥‡à¤œ बदला...</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">सà¥à¤µà¤¾à¤•à¥à¤·à¤°à¥€ आणि संदेश...</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;संदेश सतà¥à¤¯à¤¾à¤ªà¤¿à¤¤ करा...</translation>
+ </message>
+ <message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">फाइलमधून PSBT &amp;लोड करा...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">वॉलेट बंद करा...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">वॉलेट तयार करा...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">सरà¥à¤µ वॉलेट बंद करा...</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">शीरà¥à¤·à¤²à¥‡à¤– समकà¥à¤°à¤®à¤¿à¤¤ करत आहे (%1%)…</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">नेटवरà¥à¤•à¤¸à¤¹ सिंकà¥à¤°à¥‹à¤¨à¤¾à¤‡à¤ करत आहे...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">डिसà¥à¤•à¤µà¤° बà¥à¤²à¥‰à¤• अनà¥à¤•à¥à¤°à¤®à¤¿à¤¤ करत आहे...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">डिसà¥à¤•à¤µà¤° बà¥à¤²à¥‰à¤•à¥à¤¸à¤µà¤° पà¥à¤°à¤•à¥à¤°à¤¿à¤¯à¤¾ करत आहे...</translation>
+ </message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
@@ -178,6 +270,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -243,6 +356,11 @@
<context>
<name>TransactionView</name>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">कॉमा सेपरेटेड फ़ाइल</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">लेबल</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ms.ts b/src/qt/locale/bitcoin_ms.ts
index 7ed9148806..1494cbc02a 100644
--- a/src/qt/locale/bitcoin_ms.ts
+++ b/src/qt/locale/bitcoin_ms.ts
@@ -445,6 +445,24 @@ Alihkan fail data ke dalam tab semasa</translation>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_my.ts b/src/qt/locale/bitcoin_my.ts
index 7418bf8aeb..4f68c8cf2a 100644
--- a/src/qt/locale/bitcoin_my.ts
+++ b/src/qt/locale/bitcoin_my.ts
@@ -174,6 +174,24 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts
index ab2f00860e..c58017288f 100644
--- a/src/qt/locale/bitcoin_nb.ts
+++ b/src/qt/locale/bitcoin_nb.ts
@@ -269,6 +269,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Vil du tilbakestille innstillingene til utgangsverdiene, eller vil du avbryte uten å gjøre endringer?</translation>
</message>
<message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">En fatal feil har oppstått. Sjekk at filen med innstillinger er skrivbar eller prøv å kjøre med -nosettings.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Feil: Den spesifiserte datamappen "%1" finnes ikke.</translation>
</message>
@@ -321,6 +326,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Blokkrelé</translation>
</message>
<message>
+ <source>Manual</source>
+ <extracomment>Peer connection type established manually through one of several methods.</extracomment>
+ <translation type="unfinished">HÃ¥ndbok</translation>
+ </message>
+ <message>
<source>Feeler</source>
<extracomment>Short-lived peer connection type that tests the aliveness of known addresses.</extracomment>
<translation type="unfinished">Føler</translation>
@@ -345,36 +355,36 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n sekund</numerusform>
+ <numerusform>%n sekunder</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n minutt</numerusform>
+ <numerusform>%n minutter</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n time</numerusform>
+ <numerusform>%n timer</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n dag</numerusform>
+ <numerusform>%n dager</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n uke</numerusform>
+ <numerusform>%n uker</numerusform>
</translation>
</message>
<message>
@@ -384,8 +394,8 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n år</numerusform>
+ <numerusform>%n år</numerusform>
</translation>
</message>
</context>
@@ -444,10 +454,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Feil: Dumpfil versjon er ikke støttet. Denne versjonen av bitcoin-lommebok støtter kun versjon 1 dumpfiler. Fikk dumpfil med versjon %s</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Feil: Lytting etter innkommende tilkoblinger feilet (lytting returnerte feil %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Avgiftsberegning mislyktes. Fallbackfee er deaktivert. Vent et par blokker eller aktiver -fallbackfee.</translation>
</message>
@@ -552,6 +558,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kan ikke sette -peerblockfilters uten -blockfilterindex</translation>
</message>
<message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Kunne ikke gjenopprette sikkerhetskopi av lommebok.</translation>
+ </message>
+ <message>
<source>Copyright (C) %i-%i</source>
<translation type="unfinished">Kopirett © %i-%i</translation>
</message>
@@ -624,10 +636,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Feil ved lesing av neste oppføring fra lommebokdatabase</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Feil ved oppgradering av kjedetilstandsdatabase</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Feil: Ikke nok ledig diskplass for %s</translation>
</message>
@@ -656,6 +664,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Feil: Ingen %s adresser tilgjengelige.</translation>
</message>
<message>
+ <source>Error: Unable to write record to new wallet</source>
+ <translation type="unfinished">Feil: Kan ikke skrive rekord til ny lommebok</translation>
+ </message>
+ <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">Kunne ikke lytte på noen port. Bruk -listen=0 hvis det er dette du vil.</translation>
</message>
@@ -688,6 +700,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Sunnhetssjekk ved oppstart mislyktes. %s skrus av.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Finner ikke data eller er allerede brukt</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">Utilstrekkelige midler</translation>
</message>
@@ -736,12 +752,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Laster lommebok...</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Mangler beløp</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">MÃ¥ oppgi en port med -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Ingen proxyserver er spesifisert. Bruk -proxy=&lt;ip&gt; eller -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Ingen adresser tilgjengelig</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -752,10 +772,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Beskjæringsmodus kan ikke konfigureres med en negativ verdi.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Beskjæringsmodus er inkompatibel med -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Beskjæringsmodus er inkompatibel med -txindex.</translation>
</message>
@@ -768,6 +784,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Reduserer -maxconnections fra %d til %d, pga. systembegrensninger.</translation>
</message>
<message>
+ <source>Replaying blocks…</source>
+ <translation type="unfinished">Spiller av blokker på nytt …</translation>
+ </message>
+ <message>
<source>Rescanning…</source>
<translation type="unfinished">Leser gjennom igjen...</translation>
</message>
@@ -892,10 +912,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ustøttet loggingskategori %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Oppgraderer UTXO-database</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">User Agent kommentar (%s) inneholder utrygge tegn.</translation>
</message>
@@ -1187,6 +1203,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Lukk lommebok</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Gjenopprett lommebok...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Gjenopprett en lommebok fra en sikkerhetskopi</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Lukk alle lommebøker</translation>
</message>
@@ -1211,6 +1237,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ingen lommebøker tilgjengelig</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Lommebokdata</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Last lommebok sikkerhetskopi</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Gjenopprett lommebok</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Lommeboknavn</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Vindu</translation>
</message>
@@ -1251,6 +1297,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Klikk for å aktivere nettverksaktivitet.</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Synkroniserer blokkhoder (%1%)...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Feil: %1</translation>
</message>
@@ -1499,7 +1549,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">Kan ikke vise liste over undertegnere</translation>
</message>
-</context>
+ </context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1539,6 +1589,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Gjenopprett lommebok</translation>
+ </message>
+ </context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1709,13 +1767,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(av %1 GB som trengs)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB kreves for hele kjeden)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(av %n GB som trengs)</numerusform>
+ <numerusform>(av %n GB som trengs)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n GB kreves for hele kjeden)</numerusform>
+ <numerusform>(%n GB kreves for hele kjeden)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1762,10 +1833,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Siden dette er første gang programmet starter, kan du nå velge hvor %1 skal lagre sine data.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Når du klikker OK, vil %1 starte nedlasting og behandle hele den %4 blokkjeden (%2GB) fra de eldste transaksjonene i %3 når %4 først startet.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Begrens blokkjedelagring til</translation>
</message>
@@ -1870,7 +1937,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
<translation type="unfinished">%1 synkroniseres for øyeblikket. Den vil laste ned blokkhoder og blokker fra likemenn og validere dem til de når enden av blokkjeden.</translation>
</message>
- </context>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Ukjent.Synkroniser blokkhoder (%1,%2%)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -1922,6 +1993,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Minimer i stedet for å avslutte applikasjonen når vinduet lukkes. Når dette er valgt, vil applikasjonen avsluttes kun etter at Avslutte er valgt i menyen.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Alternativer som er satt i denne dialogboksen overstyres av kommandolinjen:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Ã…pne %1-oppsettsfila fra arbeidsmappen.</translation>
</message>
@@ -2082,10 +2157,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">nærmeste treff "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Alternativer som er satt i denne dialogboksen overstyres av kommandolinjen eller i konfigurasjonsfilen:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Avbryt</translation>
</message>
@@ -2104,14 +2175,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Bekreft tilbakestilling av innstillinger</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Omstart av klienten er nødvendig for å aktivere endringene.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Klienten vil bli lukket. Ønsker du å gå videre?</translation>
</message>
<message>
@@ -2332,6 +2406,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transaksjonen trenger signatur(er).</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Men ingen lommebok er lastet.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Men denne lommeboken kan ikke signere transaksjoner.)</translation>
</message>
@@ -2401,6 +2479,11 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<translation type="unfinished">Likemann</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Alder</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Retning</translation>
@@ -2571,6 +2654,10 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<translation type="unfinished">Synkroniserte Blokker</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Siste transaksjon</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">Det kartlagte Autonome Systemet som brukes til å diversifisere valg av likemenn.</translation>
</message>
@@ -2579,6 +2666,11 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<translation type="unfinished">Kartlagt AS</translation>
</message>
<message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Adresser Prosessert</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Brukeragent</translation>
</message>
@@ -3249,6 +3341,11 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<translation type="unfinished">Se over ditt transaksjonsforslag. Dette kommer til å produsere en Delvis Signert Bitcoin Transaksjon (PSBT) som du kan lagre eller kopiere og så signere med f.eks. en offline %1 lommebok, eller en PSBT kompatibel hardware lommebok.</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Vil du lage denne transaksjonen?</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Vennligst se over transaksjonen din.</translation>
@@ -3301,10 +3398,6 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Et gebyr høyere enn %1 anses som absurd høyt.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Tidsavbrudd for betalingsforespørsel</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3384,14 +3477,6 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<translation type="unfinished">Melding:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Dette er en uautorisert betalingsetterspørring.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Dette er en autorisert betalingsetterspørring.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Skriv inn en merkelapp for denne adressen for å legge den til listen av brukte adresser</translation>
</message>
@@ -3399,11 +3484,7 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">En melding som var tilknyttet bitcoinen: URI vil bli lagret med transaksjonen for din oversikt. Denne meldingen vil ikke bli sendt over Bitcoin-nettverket.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Betal Til:</translation>
- </message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -3560,35 +3641,31 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<source>(press q to shutdown and continue later)</source>
<translation type="unfinished">(trykk q for å skru av og fortsette senere)</translation>
</message>
- </context>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">trykk på q for å slå av</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">gikk ikke overens med en transaksjon med %1 bekreftelser</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/ubekreftet, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">i minnepool</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ikke i minnepool</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">forlatt</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/ubekreftet</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 bekreftelser</translation>
</message>
<message>
@@ -3634,8 +3711,8 @@ Hvis du får denne feilen burde du be forretningsdrivende om å tilby en BIP21 k
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>modner om %n blokk</numerusform>
+ <numerusform>modner om %n blokker</numerusform>
</translation>
</message>
<message>
@@ -4072,7 +4149,7 @@ Gå til Fil &gt; Åpne lommebok for å laste en lommebok.
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">&amp;Eksporter</translation>
+ <translation type="unfinished">&amp;Eksport</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
diff --git a/src/qt/locale/bitcoin_ne.ts b/src/qt/locale/bitcoin_ne.ts
index a9b0e65e42..e3ca99b20f 100644
--- a/src/qt/locale/bitcoin_ne.ts
+++ b/src/qt/locale/bitcoin_ne.ts
@@ -23,13 +23,17 @@
</message>
<message>
<source>C&amp;lose</source>
- <translation type="unfinished">बनà¥à¤¦ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+ <translation type="unfinished">छनौट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
<translation type="unfinished">भरà¥à¤–रै चयन गरेको ठेगाना सूचीबाट मेटाउनà¥à¤¹à¥‹à¤¸à¥</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">खोजà¥à¤¨à¤•à¥‹ लागि ठेगाना वा लेबल दरà¥à¤¤à¤¾ गरà¥à¤¨à¥à¤¹à¥‹à¤¸</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation type="unfinished">वरà¥à¤¤à¤®à¤¾à¤¨ टà¥à¤¯à¤¾à¤¬à¤•à¥‹ डाटालाई फाइलमा निरà¥à¤¯à¤¾à¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
</message>
@@ -42,21 +46,70 @@
<translation type="unfinished">&amp;amp;मेटाउनà¥à¤¹à¥‹à¤¸à¥</translation>
</message>
<message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">सिकà¥à¤•à¤¾à¤¹à¤°à¥ पठाउने ठेगाना छानà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ </translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">सिकà¥à¤•à¤¾à¤¹à¤°à¥ पà¥à¤°à¤¾à¤ªà¥à¤¤ गरà¥à¤¨à¥‡ ठेगाना छानà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+ </message>
+ <message>
<source>C&amp;hoose</source>
<translation type="unfinished">छनौट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥...</translation>
</message>
<message>
<source>Sending addresses</source>
- <translation type="unfinished">पठाउने ठेगानाहरू...</translation>
+ <translation type="unfinished">पठाउने ठेगानाहरू</translation>
</message>
<message>
<source>Receiving addresses</source>
<translation type="unfinished">पà¥à¤°à¤¾à¤ªà¥à¤¤ गरà¥à¤¨à¥‡ ठेगानाहरू...</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">यी भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ गरà¥à¤¨à¤•à¤¾ लागि तपाइका बिटà¥à¤•à¥‹à¤‡à¤¨ ठेगानाहरू हà¥à¤¨à¥à¥¤ सिकà¥à¤•à¤¾à¤¹à¤°à¥‚ पठाउनà¥à¤…घि रकम र पà¥à¤°à¤¾à¤ªà¥à¤¤ गरà¥à¤¨à¥‡ ठेगाना जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥¤</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">ठेगाना कपी गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
</message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">लेबल कपी गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">समà¥à¤ªà¤¾à¤¦à¤¨</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation type="unfinished">ठेगाना सà¥à¤šà¥€ निरà¥à¤¯à¤¾à¤¤</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">अलà¥à¤ªà¤µà¤¿à¤°à¤¾à¤®à¤²à¥‡ छà¥à¤Ÿà¥à¤Ÿà¤¿à¤à¤•à¥‹ फाइल</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
+ <translation type="unfinished">ठेगाना सà¥à¤šà¥€ %1मा बचत गरà¥à¤¨à¥‡ पà¥à¤°à¤¯à¤¾à¤¸à¤®à¤¾ तà¥à¤°à¥à¤Ÿà¤¿ भà¤à¤•à¥‹ छ। कृपया पà¥à¤¨à¤ƒ पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥¤</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">निरà¥à¤¯à¤¾à¤¤ असफल</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">लेबल</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">ठेगाना</translation>
+ </message>
</context>
<context>
<name>AskPassphraseDialog</name>
@@ -76,6 +129,30 @@
<source>Repeat new passphrase</source>
<translation type="unfinished">नयाठपासफà¥à¤°à¥‡à¤œ दोहोरà¥à¤¯à¤¾à¤‰à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
</message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation type="unfinished">वालेट इनà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ </translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation type="unfinished">वालेट इनà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤¸à¤¨ सà¥à¤¨à¤¿à¤¶à¥à¤šà¤¿à¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">वालेट इनà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ भयो</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation type="unfinished">अब वालेट इनà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ भà¤à¤•à¥‹ छ।</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation type="unfinished">वालेट इनà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤¸à¤¨ असफल </translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation type="unfinished">वालेट अनलक असफल </translation>
+ </message>
</context>
<context>
<name>BanTableModel</name>
@@ -144,10 +221,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">तà¥à¤°à¥à¤Ÿà¤¿: आगमन कनेकà¥à¤¸à¤¨à¤®à¤¾ सà¥à¤¨à¥à¤¨à¥‡ कारà¥à¤¯ असफल भयो (सà¥à¤¨à¥à¤¨à¥‡ कारà¥à¤¯à¤²à¥‡ तà¥à¤°à¥à¤Ÿà¤¿ %s फरà¥à¤•à¤¾à¤¯à¥‹)</translation>
- </message>
- <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation type="unfinished">maxtxfee=&amp;lt;रकम&amp;gt;: का लागि अमानà¥à¤¯ रकम &amp;apos;%s&amp;apos; (कारोबारलाई अडà¥à¤•à¤¨ नदिन अनिवारà¥à¤¯ रूपमा कमà¥à¤¤à¤¿à¤®à¤¾ %s को नà¥à¤¯à¥‚नतम रिले शà¥à¤²à¥à¤• हà¥à¤¨à¥ परà¥à¤›)</translation>
</message>
@@ -288,6 +361,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -339,7 +433,7 @@
</message>
<message>
<source>Balances</source>
- <translation type="unfinished">बà¥à¤¯à¤¾à¤²à¥‡à¤¨à¥à¤¸</translation>
+ <translation type="unfinished">बà¥à¤¯à¤¾à¤²à¥‡à¤¨à¥à¤¸à¤¹à¤°à¥</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
@@ -357,6 +451,11 @@
<extracomment>Title of Peers Table column which contains the peer's User Agent string.</extracomment>
<translation type="unfinished">पà¥à¤°à¤¯à¥‹à¤—करà¥à¤¤à¤¾ à¤à¤œà¥‡à¤¨à¥à¤Ÿ</translation>
</message>
+ <message>
+ <source>Address</source>
+ <extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
+ <translation type="unfinished">ठेगाना</translation>
+ </message>
</context>
<context>
<name>RPCConsole</name>
@@ -370,6 +469,13 @@
</message>
</context>
<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">लेबल</translation>
+ </message>
+ </context>
+<context>
<name>SendCoinsDialog</name>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
@@ -397,7 +503,7 @@
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">बिटकोइनमा संलगà¥à¤¨ गरिà¤à¤•à¥‹ सनà¥à¤¦à¥‡à¤¶: तपाईंको मधà¥à¤¯à¤¸à¥à¤¥à¤•à¥‹ लागि कारोबारको साथमा भणà¥à¤¡à¤¾à¤°à¤£ गरिने URI । नोट: यो सनà¥à¤¦à¥‡à¤¶ बिटकोइन नेटवरà¥à¤• मारà¥à¤«à¤¤ पठाइने छैन ।</translation>
</message>
- </context>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
@@ -432,6 +538,33 @@
</message>
</context>
<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">लेबल</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">अलà¥à¤ªà¤µà¤¿à¤°à¤¾à¤®à¤²à¥‡ छà¥à¤Ÿà¥à¤Ÿà¤¿à¤à¤•à¥‹ फाइल</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">लेबल</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">ठेगाना</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">निरà¥à¤¯à¤¾à¤¤ असफल</translation>
+ </message>
+ </context>
+<context>
<name>WalletView</name>
<message>
<source>&amp;Export</source>
diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts
index 7411fdd82b..19644522e3 100644
--- a/src/qt/locale/bitcoin_nl.ts
+++ b/src/qt/locale/bitcoin_nl.ts
@@ -137,19 +137,19 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>Show passphrase</source>
- <translation type="unfinished">Laat wachtwoordzin zien</translation>
+ <translation type="unfinished">Toon wachtwoordzin</translation>
</message>
<message>
<source>Encrypt wallet</source>
- <translation type="unfinished">Versleutel portemonnee</translation>
+ <translation type="unfinished">Versleutel wallet</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation type="unfinished">Deze bewerking heeft uw portemonnee wachtwoordzin nodig om de portemonnee te ontgrendelen.</translation>
+ <translation type="unfinished">Deze bewerking heeft uw wallet passphrase (wachtwoord) nodig om de wallet te ontgrendelen.</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation type="unfinished">Portemonnee ontgrendelen</translation>
+ <translation type="unfinished">Wallet ontgrendelen</translation>
</message>
<message>
<source>Change passphrase</source>
@@ -157,55 +157,55 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation type="unfinished">Bevestig de versleuteling van de portemonnee</translation>
+ <translation type="unfinished">Bevestig de versleuteling van de wallet</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished">Waarschuwing: Als u uw portemonnee versleutelt en uw wachtwoord vergeet, zult u &lt;b&gt;AL UW BITCOINS VERLIEZEN&lt;/b&gt;!</translation>
+ <translation type="unfinished">Waarschuwing: Als u uw wallet versleutelt en uw wachtwoord vergeet, zult u &lt;b&gt;AL UW BITCOIN VERLIEZEN&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation type="unfinished">Weet u zeker dat u uw portemonnee wilt versleutelen?</translation>
+ <translation type="unfinished">Weet u zeker dat u uw wallet wilt versleutelen?</translation>
</message>
<message>
<source>Wallet encrypted</source>
- <translation type="unfinished">Portemonnee versleuteld</translation>
+ <translation type="unfinished">Wallet versleuteld</translation>
</message>
<message>
<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">Voer de nieuwe wachtwoordzin in voor de portemonnee.&lt;br/&gt;Gebruik a.u.b. een wachtwoordzin van &lt;b&gt;tien of meer willekeurige karakters&lt;/b&gt;, of &lt;b&gt;acht of meer woorden&lt;/b&gt;.</translation>
+ <translation type="unfinished">Voer de nieuwe passphrase (wachtwoordzin) in voor de wallet.&lt;br/&gt;Gebruik a.u.b. een wachtwoordzin van &lt;b&gt;tien of meer willekeurige karakters&lt;/b&gt;, of &lt;b&gt;acht of meer woorden&lt;/b&gt;.</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
- <translation type="unfinished">Voer de oude wachtwoordzin en de nieuwe wachtwoordzin in voor de portemonnee.</translation>
+ <translation type="unfinished">Voer de oude en de nieuwe passphrase (wachtwoordzin) in voor de wallet.</translation>
</message>
<message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation type="unfinished">Onthoud dat het versleutelen van uw portemonnee uw bitcoins niet volledig kan beschermen tegen diefstal, bijvoorbeeld door malware die uw computer infecteert.</translation>
+ <translation type="unfinished">Onthoud dat het versleutelen van uw wallet uw bitcoin niet volledig kan beschermen tegen diefstal, bijvoorbeeld door malware die uw computer infecteert.</translation>
</message>
<message>
<source>Wallet to be encrypted</source>
- <translation type="unfinished">Portemonnee om te versleutelen</translation>
+ <translation type="unfinished">Wallet om te versleutelen</translation>
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation type="unfinished">Je portemonnee gaat versleuteld worden.</translation>
+ <translation type="unfinished">Je wallet gaat versleuteld worden.</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation type="unfinished">Je portemonnee is nu versleuteld.</translation>
+ <translation type="unfinished">Je wallet is nu versleuteld.</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation type="unfinished">BELANGRIJK: Elke eerder gemaakte backup van uw portemonneebestand dient u te vervangen door het nieuw gegenereerde, versleutelde portemonneebestand. Om veiligheidsredenen zullen eerdere backups van het niet versleutelde portemonneebestand onbruikbaar worden zodra u uw nieuwe, versleutelde, portemonnee begint te gebruiken.</translation>
+ <translation type="unfinished">BELANGRIJK: Elke eerder gemaakte backup van uw walletbestand dient u te vervangen door het nieuw gegenereerde, versleutelde walletbestand. Om veiligheidsredenen zullen eerdere backups van het niet versleutelde walletbestand onbruikbaar worden zodra u uw nieuwe, versleutelde wallet begint te gebruiken.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
- <translation type="unfinished">Portemonneeversleuteling mislukt</translation>
+ <translation type="unfinished">Versleuteling van wallet mislukt</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation type="unfinished">Portemonneeversleuteling mislukt door een interne fout. Uw portemonnee is niet versleuteld.</translation>
+ <translation type="unfinished">Walletversleuteling mislukt door een interne fout. Je wallet werd niet versleuteld.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
@@ -213,15 +213,15 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>Wallet unlock failed</source>
- <translation type="unfinished">Portemonnee openen mislukt</translation>
+ <translation type="unfinished">Wallet openen mislukt</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation type="unfinished">Het opgegeven wachtwoord voor de portemonnee ontsleuteling is niet correct.</translation>
+ <translation type="unfinished">Het opgegeven wachtwoord voor de ontsleuteling van de wallet is niet correct.</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation type="unfinished">Portemonneewachtwoord is met succes gewijzigd.</translation>
+ <translation type="unfinished">Wallet passphrase (wachtwoord) werd succesvol gewijzigd.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
@@ -242,6 +242,10 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Configuratiebestand %1 zou beschadigd of ongeldig kunnen zijn.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Ongecontroleerde uitzondering</translation>
</message>
@@ -253,11 +257,7 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
<source>Internal error</source>
<translation type="unfinished">interne error</translation>
</message>
- <message>
- <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <translation type="unfinished">Een interne fout heeft plaatsgevonden. %1 zal proberen om veilig door te gaan. Dit is een onverwacht probleem wat vermeldt kan worden zoals hieronder beschreven staat.</translation>
- </message>
-</context>
+ </context>
<context>
<name>QObject</name>
<message>
@@ -356,36 +356,36 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n seconde(s)</numerusform>
+ <numerusform>%n seconde(s)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n minuten</numerusform>
+ <numerusform>%n minuten</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n uur</numerusform>
+ <numerusform>%n uur</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n dag(en)</numerusform>
+ <numerusform>%n dag(en)</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n weken</numerusform>
+ <numerusform>%n weken</numerusform>
</translation>
</message>
<message>
@@ -395,8 +395,8 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n jaar</numerusform>
+ <numerusform>%n jaar</numerusform>
</translation>
</message>
<message>
@@ -420,7 +420,7 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
- <translation type="unfinished">%s is corrupt. Probeer de portemonnee tool bitcoin-wallet om het probleem op te lossen of een backup terug te zetten.</translation>
+ <translation type="unfinished">%s beschadigd. Probeer de wallet tool bitcoin-wallet voor herstel of een backup terug te zetten.</translation>
</message>
<message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
@@ -428,7 +428,7 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
- <translation type="unfinished">Kan portemonnee niet downgraden van versie %i naar version %i. Portemonneeversie ongewijzigd.</translation>
+ <translation type="unfinished">Kan wallet niet downgraden van versie %i naar version %i. Walletversie ongewijzigd.</translation>
</message>
<message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
@@ -436,7 +436,7 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>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>
- <translation type="unfinished">Kan een non HD split portemonnee niet upgraden van versie %i naar versie %i zonder pre split keypool te ondersteunen. Gebruik versie %i of specificeer geen versienummer.</translation>
+ <translation type="unfinished">Kan een non HD split wallet niet upgraden van versie %i naar versie %i zonder pre split keypool te ondersteunen. Gebruik versie %i of specificeer geen versienummer.</translation>
</message>
<message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
@@ -448,7 +448,7 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
- <translation type="unfinished">Fout bij het lezen van %s! Transactiegegevens kunnen ontbreken of onjuist zijn. Portemonnee opnieuw scannen.</translation>
+ <translation type="unfinished">Fout bij het lezen van %s! Transactiegegevens kunnen ontbreken of onjuist zijn. Wallet opnieuw scannen.</translation>
</message>
<message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
@@ -467,10 +467,6 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
<translation type="unfinished">Fout: Legacy wallets ondersteunen alleen "legacy", "p2sh-segwit" en "bech32" adres types</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Fout: luisteren naar binnenkomende verbindingen mislukt (luisteren gaf foutmelding %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Het inschatten van de vergoeding is gefaald. Fallbackfee is uitgeschakeld. Wacht een aantal blocks of schakel -fallbackfee in.</translation>
</message>
@@ -500,7 +496,7 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
- <translation type="unfinished">Geen portemonneebestandsformaat opgegeven. Om createfromdump te gebruiken, moet -format=&lt;format&gt; opgegeven worden.</translation>
+ <translation type="unfinished">Geen walletbestandsformaat opgegeven. Om createfromdump te gebruiken, moet -format=&lt;format&gt; opgegeven worden.</translation>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
@@ -515,12 +511,16 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
<translation type="unfinished">Prune is ingesteld op minder dan het minimum van %d MiB. Gebruik a.u.b. een hoger aantal.</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">Prune mode is niet compatibel met -reindex-chainstate. Gebruik in plaats hiervan volledige -reindex.</translation>
+ </message>
+ <message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
- <translation type="unfinished">Prune: laatste wallet synchronisatie gaat verder terug dan de middels beperkte data. U moet -reindex gebruiken (downloadt opnieuw de gehele blokketen voor een pruned node)</translation>
+ <translation type="unfinished">Prune: laatste wallet synchronisatie gaat verder terug dan de pruned gegevens. Je moet herindexeren met -reindex (de hele blokketen opnieuw downloaden in geval van een pruned node)</translation>
</message>
<message>
<source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
- <translation type="unfinished">SQLite Databank: Onbekende sqlite portemonee schema versie %d. Enkel %d wordt ondersteund.</translation>
+ <translation type="unfinished">SQLiteDatabase: Onbekende sqlite wallet schema versie %d. Alleen versie %d wordt ondersteund.</translation>
</message>
<message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
@@ -536,8 +536,7 @@ Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation
</message>
<message>
<source>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>
- <translation type="unfinished">Deze fout komt mogelijks voor wanneer de portefeuille niet correct is afgesloten en dat deze de laatste keer geladen werd met een nieuwere versie van de Berkeley DB.
-Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeuille de laatste keer werd geladen.</translation>
+ <translation type="unfinished">Deze fout komt mogelijk voor wanneer de wallet niet correct werd afgesloten en de laatste keer werd geladen met een nieuwere versie van de Berkeley DB. Indien dit het geval is, gebruik aub de software waarmee deze wallet de laatste keer werd geladen.</translation>
</message>
<message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
@@ -565,15 +564,23 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
- <translation type="unfinished">Onbekend portemonneebestandsformaat "%s" opgegeven. Kies aub voor "bdb" of "sqlite".</translation>
+ <translation type="unfinished">Onbekend walletbestandsformaat "%s" opgegeven. Kies aub voor "bdb" of "sqlite".</translation>
+ </message>
+ <message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Niet ondersteund chainstate databaseformaat gevonden. Herstart aub met -reindex-chainstate. Dit zal de chainstate database opnieuw opbouwen.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Wallet succesvol aangemaakt. Het oude wallettype wordt uitgefaseerd en ondersteuning voor het maken en openen van verouderde wallets zal in de toekomst komen te vervallen.</translation>
</message>
<message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
- <translation type="unfinished">Waarschuwing: Dumpbestandsformaat portemonnee "%s" komt niet overeen met het op de command line gespecificeerde formaat "%s".</translation>
+ <translation type="unfinished">Waarschuwing: Dumpbestand walletformaat "%s" komt niet overeen met het op de command line gespecificeerde formaat "%s".</translation>
</message>
<message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <translation type="unfinished">Waarschuwing: Geheime sleutels gedetecteerd in portemonnee {%s} met uitgeschakelde geheime sleutels</translation>
+ <translation type="unfinished">Waarschuwing: Geheime sleutels gedetecteerd in wallet {%s} met uitgeschakelde geheime sleutels</translation>
</message>
<message>
<source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
@@ -616,6 +623,88 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Mag niet schrijven naar gegevensmap '%s'; controleer bestandsrechten.</translation>
</message>
<message>
+ <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">De -txindex upgrade die door een eerdere versie is gestart, kan niet worden voltooid. Herstart opnieuw met de vorige versie of voer een volledige -reindex uit.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s verzoekt om te luisteren op poort %u. Deze poort wordt als "slecht" beschouwd en het is daarom onwaarschijnlijk dat Bitcoin Core peers er verbinding mee maken. Zie doc/p2p-bad-ports.md voor details en een volledige lijst.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate optie is niet compatibel met -blockfilterindex. Schakel -blockfilterindex tijdelijk uit aub en gebruik -reindex-chainstate, of vervang -reindex-chainstate met -reindex om alle indices volledig opnieuw op te bouwen.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate optie is niet compatibel met -coinstatsindex. Schakel -coinstatsindex tijdelijk uit aub en gebruik -reindex-chainstate, of vervang -reindex-chainstate met -reindex om alle indices volledig opnieuw op te bouwen.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate optie is niet compatibel met -txindex. Schakel -txindex tijdelijk uit aub en gebruik -reindex-chainstate, of vervang -reindex-chainstate met -reindex om alle indices volledig opnieuw op te bouwen.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Aangenomen-geldig: Laatste walletsynchronisatie gaat verder dan de beschikbare blokgegevens. Je moet wachten tot de validatie van de blokketen op de achtergrond meer blokken heeft gedownload.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Kan geen specifieke verbindingen verstrekken en addrman tegelijkertijd uitgaande verbindingen laten vinden.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Fout bij laden %s: Externe signer wallet wordt geladen zonder gecompileerde ondersteuning voor externe signers</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Fout: adresboekgegevens in portemonnee kunnen niet worden geïdentificeerd als behorend tot gemigreerde portemonnees</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">Fout: dubbele beschrijvingen gemaakt tijdens migratie. Uw portemonnee is mogelijk corrupt.</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Fout: transactie %s in portemonnee kan niet worden geïdentificeerd als behorend tot gemigreerde portemonnees</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">Fout: kan descriptors voor deze verouderde portemonnee niet produceren. Zorg ervoor dat de portemonnee eerst is ontgrendeld</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Kan de naam van het ongeldige peers.dat bestand niet hernoemen. Verplaats of verwijder het en probeer het opnieuw.</translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">Incompatibele opties: -dnsseed=1 is expliciet gespecificeerd, maar -onlynet verbiedt verbindingen met IPv4/IPv6</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">Uitgaande verbindingen beperkt tot Tor (-onlynet=onion) maar de proxy voor het bereiken van het Tor-netwerk is expliciet verboden: -onion=0</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Uitgaande verbindingen beperkt tot Tor (-onlynet=onion) maar de proxy voor het bereiken van het Tor netwerk is niet verstrekt (geen -proxy= en geen -onion= opgegeven) of het is expliciet verboden (-onion=0)</translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">Niet-herkende descriptor gevonden. Portemonnee laden %s
+
+De portemonnee is mogelijk gemaakt op een nieuwere versie.
+Probeer de nieuwste softwareversie uit te voeren.
+</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+Kan mislukte migratie niet opschonen</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Configuratie-instellingen voor %s alleen toegepast op %s network wanneer in [%s] sectie.</translation>
</message>
@@ -661,7 +750,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Error initializing wallet database environment %s!</source>
- <translation type="unfinished">Probleem met initializeren van de database-omgeving %s!</translation>
+ <translation type="unfinished">Probleem met initializeren van de wallet database-omgeving %s!</translation>
</message>
<message>
<source>Error loading %s</source>
@@ -673,11 +762,11 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Error loading %s: Wallet corrupted</source>
- <translation type="unfinished">Fout bij het laden van %s: Portomonnee corrupt</translation>
+ <translation type="unfinished">Fout bij het laden van %s: Wallet beschadigd</translation>
</message>
<message>
<source>Error loading %s: Wallet requires newer version of %s</source>
- <translation type="unfinished">Fout bij laden %s: Portemonnee vereist een nieuwere versie van %s</translation>
+ <translation type="unfinished">Fout bij laden %s: Wallet vereist een nieuwere versie van %s</translation>
</message>
<message>
<source>Error loading block database</source>
@@ -693,11 +782,15 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Error reading next record from wallet database</source>
- <translation type="unfinished">Fout bij het lezen van het volgende record in de portemonneedatabase</translation>
+ <translation type="unfinished">Fout bij het lezen van het volgende record in de walletdatabase</translation>
+ </message>
+ <message>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">Fout: kan watchonly tx niet toevoegen aan watchonly-portemonnee</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Fout bij het upgraden van de ketenstaat database</translation>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">Fout: kan alleen-kijken-transacties niet verwijderen</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
@@ -712,6 +805,10 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Fout: Checksum van dumpbestand komt niet overeen. Berekend %s, verwacht %s</translation>
</message>
<message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">Fout: kan geen nieuwe watchonly-portemonnee maken</translation>
+ </message>
+ <message>
<source>Error: Got key that was not hex: %s</source>
<translation type="unfinished">Fout: Verkregen key was geen hex: %s</translation>
</message>
@@ -732,12 +829,40 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Fout: Geen %s adressen beschikbaar</translation>
</message>
<message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">Fout: niet alle watchonly tx's kunnen worden verwijderd</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Fout: deze portemonnee gebruikt SQLite al</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">Fout: deze portemonnee is al een descriptorportefeuille</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">Fout: Kan niet beginnen met het lezen van alle records in de database</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Fout: kan geen back-up van uw portemonnee maken</translation>
+ </message>
+ <message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">Fout: Kan versie %u niet als een uint32_t verwerken</translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Fout: kan niet alle records in de database lezen</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">Fout: kan adresboekgegevens voor alleen kijken niet verwijderen</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
- <translation type="unfinished">Fout: Kan record niet naar nieuwe portemonnee schrijven</translation>
+ <translation type="unfinished">Fout: Kan record niet naar nieuwe wallet schrijven</translation>
</message>
<message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
@@ -745,7 +870,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Failed to rescan the wallet during initialization</source>
- <translation type="unfinished">Portemonnee herscannen tijdens initialisatie mislukt</translation>
+ <translation type="unfinished">Herscannen van de wallet tijdens initialisatie mislukt</translation>
</message>
<message>
<source>Failed to verify database</source>
@@ -757,7 +882,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Ignoring duplicate -wallet %s.</source>
- <translation type="unfinished">Negeren gedupliceerde -portemonnee %s</translation>
+ <translation type="unfinished">Negeren gedupliceerde -wallet %s</translation>
</message>
<message>
<source>Importing…</source>
@@ -816,6 +941,10 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Ongeldig netmask gespecificeerd in -whitelist: '%s'</translation>
</message>
<message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">Luisteren naar binnenkomende verbindingen mislukt (luisteren gaf foutmelding %s)</translation>
+ </message>
+ <message>
<source>Loading P2P addresses…</source>
<translation type="unfinished">P2P-adressen laden...</translation>
</message>
@@ -829,7 +958,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Loading wallet…</source>
- <translation type="unfinished">Portemonnee laden...</translation>
+ <translation type="unfinished">Wallet laden...</translation>
</message>
<message>
<source>Missing amount</source>
@@ -848,10 +977,6 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Geen adressen beschikbaar</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Geen proxy server gedefinieerd. Gebruik -proxy=&lt;ip&gt;of -proxy=&lt;ip:port&gt;.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Niet genoeg file descriptors beschikbaar.</translation>
</message>
@@ -860,10 +985,6 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Prune kan niet worden geconfigureerd met een negatieve waarde.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Prune-modus is niet compatibel met -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Prune-modus is niet compatible met -txindex</translation>
</message>
@@ -941,7 +1062,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation type="unfinished">De portemonnee vermijdt minder te betalen dan de minimale doorgeef vergoeding.</translation>
+ <translation type="unfinished">De wallet vermijdt minder te betalen dan de minimale vergoeding voor het doorgeven.</translation>
</message>
<message>
<source>This is experimental software.</source>
@@ -964,6 +1085,10 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Transactiebedragen moeten positief zijn</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Transactie change output is buiten bereik</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">Transactie heeft een te lange mempoolketen</translation>
</message>
@@ -980,6 +1105,10 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Transactie te groot</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Kan geen geheugen toekennen voor -maxsigcachesize: '%s' MiB</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished">Niet in staat om aan %s te binden op deze computer (bind gaf error %s)</translation>
</message>
@@ -992,6 +1121,10 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Kan de PID file niet creëren. '%s': %s</translation>
</message>
<message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">Kan UTXO niet vinden voor externe invoer</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation type="unfinished">Niet mogelijk initiële sleutels te genereren</translation>
</message>
@@ -1012,6 +1145,10 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Niet mogelijk ok HTTP-server te starten. Zie debuglogboek voor details.</translation>
</message>
<message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">Kan de portemonnee niet verwijderen voordat deze wordt gemigreerd</translation>
+ </message>
+ <message>
<source>Unknown -blockfilterindex value %s.</source>
<translation type="unfinished">Onbekende -blokfilterindexwaarde %s.</translation>
</message>
@@ -1032,12 +1169,12 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Onbekende nieuwe regels geactiveerd (versionbit %i)</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">Niet-ondersteunde logcategorie %s=%s.</translation>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">Niet-ondersteund globaal logniveau -loglevel= %s. Geldige waarden: %s .</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Upgraden UTXO-database</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Niet-ondersteunde logcategorie %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -1049,11 +1186,11 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Verifying wallet(s)…</source>
- <translation type="unfinished">Portemonnee(s) controleren...</translation>
+ <translation type="unfinished">Wallet(s) controleren...</translation>
</message>
<message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
- <translation type="unfinished">Portemonnee moest herschreven worden: Herstart %s om te voltooien</translation>
+ <translation type="unfinished">Wallet moest herschreven worden: Herstart %s om te voltooien</translation>
</message>
</context>
<context>
@@ -1064,7 +1201,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Show general overview of wallet</source>
- <translation type="unfinished">Toon algemeen overzicht van uw portemonnee</translation>
+ <translation type="unfinished">Toon algemeen overzicht van uw wallet</translation>
</message>
<message>
<source>&amp;Transactions</source>
@@ -1072,7 +1209,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Browse transaction history</source>
- <translation type="unfinished">Blader door transactiegescheidenis</translation>
+ <translation type="unfinished">Blader door transactie geschiedenis </translation>
</message>
<message>
<source>E&amp;xit</source>
@@ -1111,10 +1248,6 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">&amp;Minimaliseren</translation>
</message>
<message>
- <source>Wallet:</source>
- <translation type="unfinished">Portemonnee:</translation>
- </message>
- <message>
<source>Network activity disabled.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">Netwerkactiviteit gestopt.</translation>
@@ -1129,11 +1262,11 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Backup wallet to another location</source>
- <translation type="unfinished">Backup portemonnee naar een andere locatie</translation>
+ <translation type="unfinished">Backup wallet naar een andere locatie</translation>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
- <translation type="unfinished">Wijzig het wachtwoord voor uw portemonneversleuteling</translation>
+ <translation type="unfinished">Wijzig het wachtwoord voor de wallet versleuteling</translation>
</message>
<message>
<source>&amp;Send</source>
@@ -1149,15 +1282,15 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
- <translation type="unfinished">&amp;Versleutel Portemonnee...</translation>
+ <translation type="unfinished">&amp;Versleutel wallet...</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation type="unfinished">Versleutel de geheime sleutels die bij uw portemonnee horen</translation>
+ <translation type="unfinished">Versleutel het geheime sleutelmateriaal dat bij uw wallet hoort</translation>
</message>
<message>
<source>&amp;Backup Wallet…</source>
- <translation type="unfinished">&amp;Backup portemonnee...</translation>
+ <translation type="unfinished">&amp;Backup wallet...</translation>
</message>
<message>
<source>&amp;Change Passphrase…</source>
@@ -1169,7 +1302,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Onderteken berichten met uw Bitcoin adressen om te bewijzen dat u deze adressen bezit</translation>
+ <translation type="unfinished">Onderteken berichten met uw Bitcoinadressen om te bewijzen dat u deze adressen bezit</translation>
</message>
<message>
<source>&amp;Verify message…</source>
@@ -1177,7 +1310,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation type="unfinished">Verifiëer handtekeningen om zeker te zijn dat de berichten zijn ondertekend met de gespecificeerde Bitcoin adressen</translation>
+ <translation type="unfinished">Verifiëer handtekeningen om zeker te zijn dat de berichten zijn ondertekend met de gespecificeerde Bitcoinadressen</translation>
</message>
<message>
<source>&amp;Load PSBT from file…</source>
@@ -1189,15 +1322,15 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Close Wallet…</source>
- <translation type="unfinished">Portemonnee Sluiten...</translation>
+ <translation type="unfinished">Wallet sluiten...</translation>
</message>
<message>
<source>Create Wallet…</source>
- <translation type="unfinished">Creëer portemonnee...</translation>
+ <translation type="unfinished">Maak wallet...</translation>
</message>
<message>
<source>Close All Wallets…</source>
- <translation type="unfinished">Sluit Alle Wallets…</translation>
+ <translation type="unfinished">Sluit alle wallets…</translation>
</message>
<message>
<source>&amp;File</source>
@@ -1258,8 +1391,8 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n blok(ken) transactiegeschiedenis verwerkt.</numerusform>
+ <numerusform>%n blok(ken) transactiegeschiedenis verwerkt.</numerusform>
</translation>
</message>
<message>
@@ -1296,7 +1429,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Load Partially Signed Bitcoin Transaction</source>
- <translation type="unfinished">Laad gedeeltelijk ondertekende Bitcoin-transactie</translation>
+ <translation type="unfinished">Laad gedeeltelijk ondertekende Bitcoin transactie</translation>
</message>
<message>
<source>Load PSBT from &amp;clipboard…</source>
@@ -1328,19 +1461,29 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Open Wallet</source>
- <translation type="unfinished">Portemonnee Openen</translation>
+ <translation type="unfinished">Wallet openen</translation>
</message>
<message>
<source>Open a wallet</source>
- <translation type="unfinished">Open een portemonnee</translation>
+ <translation type="unfinished">Open een wallet</translation>
</message>
<message>
<source>Close wallet</source>
- <translation type="unfinished">Portemonnee Sluiten</translation>
+ <translation type="unfinished">Wallet sluiten</translation>
+ </message>
+ <message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Wallet herstellen...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Herstel een wallet uit een backupbestand</translation>
</message>
<message>
<source>Close all wallets</source>
- <translation type="unfinished">Sluit alle portemonnees</translation>
+ <translation type="unfinished">Alle wallets sluiten</translation>
</message>
<message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
@@ -1356,11 +1499,31 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>default wallet</source>
- <translation type="unfinished">standaard portemonnee</translation>
+ <translation type="unfinished">standaard wallet</translation>
</message>
<message>
<source>No wallets available</source>
- <translation type="unfinished">Geen portefeuilles beschikbaar</translation>
+ <translation type="unfinished">Geen wallets beschikbaar</translation>
+ </message>
+ <message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Walletgegevens</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Backupwallet laden</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Wallet herstellen</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Walletnaam</translation>
</message>
<message>
<source>&amp;Window</source>
@@ -1370,12 +1533,20 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<source>Main Window</source>
<translation type="unfinished">Hoofdscherm</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Verbergen</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">T&amp;oon</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n actieve verbinding(en) met het Bitcoin-netwerk.</numerusform>
+ <numerusform>%n actieve verbinding(en) met het Bitcoin-netwerk.</numerusform>
</translation>
</message>
<message>
@@ -1399,6 +1570,10 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<translation type="unfinished">Netwerkactiviteit inschakelen</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Blokhoofden synchroniseren (%1%)...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Fout: %1</translation>
</message>
@@ -1419,12 +1594,6 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</translation>
</message>
<message>
- <source>Wallet: %1
-</source>
- <translation type="unfinished">Portemonnee: %1
-</translation>
- </message>
- <message>
<source>Address: %1
</source>
<translation type="unfinished">Adres: %1
@@ -1452,11 +1621,11 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation type="unfinished">Portemonnee is &lt;b&gt;versleuteld&lt;/b&gt; en momenteel &lt;b&gt;geopend&lt;/b&gt;</translation>
+ <translation type="unfinished">Wallet is &lt;b&gt;versleuteld&lt;/b&gt; en momenteel &lt;b&gt;geopend&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation type="unfinished">Portemonnee is &lt;b&gt;versleuteld&lt;/b&gt; en momenteel &lt;b&gt;gesloten&lt;/b&gt;</translation>
+ <translation type="unfinished">Wallet is &lt;b&gt;versleuteld&lt;/b&gt; en momenteel &lt;b&gt;gesloten&lt;/b&gt;</translation>
</message>
<message>
<source>Original message:</source>
@@ -1626,7 +1795,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
<message>
<source>Create Wallet</source>
<extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
- <translation type="unfinished">Creëer wallet</translation>
+ <translation type="unfinished">Wallet aanmaken</translation>
</message>
<message>
<source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
@@ -1635,48 +1804,52 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<source>Create wallet failed</source>
- <translation type="unfinished">Aanmaken wallet mislukt</translation>
+ <translation type="unfinished">Wallet aanmaken mislukt</translation>
</message>
<message>
<source>Create wallet warning</source>
- <translation type="unfinished">Aanmaken wallet waarschuwing</translation>
+ <translation type="unfinished">Wallet aanmaken waarschuwing</translation>
</message>
<message>
<source>Can't list signers</source>
<translation type="unfinished">Kan geen lijst maken van ondertekenaars</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Teveel externe ondertekenaars gevonden</translation>
+ </message>
</context>
<context>
<name>LoadWalletsActivity</name>
<message>
<source>Load Wallets</source>
<extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
- <translation type="unfinished">Portemonnees laden</translation>
+ <translation type="unfinished">Wallets laden</translation>
</message>
<message>
<source>Loading wallets…</source>
<extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
- <translation type="unfinished">Portemonnees laden…</translation>
+ <translation type="unfinished">Wallets laden…</translation>
</message>
</context>
<context>
<name>OpenWalletActivity</name>
<message>
<source>Open wallet failed</source>
- <translation type="unfinished">Openen van portemonnee is mislukt</translation>
+ <translation type="unfinished">Wallet openen mislukt</translation>
</message>
<message>
<source>Open wallet warning</source>
- <translation type="unfinished">Openen van portemonnee heeft een waarschuwing</translation>
+ <translation type="unfinished">Wallet openen waarschuwing</translation>
</message>
<message>
<source>default wallet</source>
- <translation type="unfinished">standaard portemonnee</translation>
+ <translation type="unfinished">standaard wallet</translation>
</message>
<message>
<source>Open Wallet</source>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
- <translation type="unfinished">Portemonnee Openen</translation>
+ <translation type="unfinished">Wallet openen</translation>
</message>
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
@@ -1685,49 +1858,73 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Wallet herstellen</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Herstellen wallet &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Wallet herstellen mislukt</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Wallet herstellen waarschuwing</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Wallet herstellen melding</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
- <translation type="unfinished">Portemonnee Sluiten</translation>
+ <translation type="unfinished">Wallet sluiten</translation>
</message>
<message>
<source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
- <translation type="unfinished">Weet je zeker dat je portemonnee &lt;i&gt;%1&lt;/i&gt; wil sluiten?</translation>
+ <translation type="unfinished">Weet je zeker dat je wallet &lt;i&gt;%1&lt;/i&gt; wilt sluiten?</translation>
</message>
<message>
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
- <translation type="unfinished">De portemonee te lang gesloten houden kan leiden tot het moeten hersynchroniseren van de hele keten als snoeien aktief is.</translation>
+ <translation type="unfinished">De wallet te lang gesloten houden kan leiden tot het moeten hersynchroniseren van de hele keten als pruning actief is.</translation>
</message>
<message>
<source>Close all wallets</source>
- <translation type="unfinished">Sluit alle portemonnees</translation>
+ <translation type="unfinished">Alle wallets sluiten</translation>
</message>
<message>
<source>Are you sure you wish to close all wallets?</source>
- <translation type="unfinished">Ben je zeker dat je alle portefeuilles wilt sluiten?</translation>
+ <translation type="unfinished">Weet je zeker dat je alle wallets wilt sluiten?</translation>
</message>
</context>
<context>
<name>CreateWalletDialog</name>
<message>
<source>Create Wallet</source>
- <translation type="unfinished">Creëer wallet</translation>
+ <translation type="unfinished">Wallet aanmaken</translation>
</message>
<message>
<source>Wallet Name</source>
- <translation type="unfinished">Wallet Naam</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation type="unfinished">Portemonnee</translation>
+ <translation type="unfinished">Walletnaam</translation>
</message>
<message>
<source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
- <translation type="unfinished">Versleutel je portemonnee. Je portemonnee zal versleuteld zijn met een wachtwoordzin naar eigen keuze.</translation>
+ <translation type="unfinished">Versleutel de wallet. De wallet zal versleuteld zijn met een passphrase (wachtwoord) naar eigen keuze.</translation>
</message>
<message>
<source>Encrypt Wallet</source>
- <translation type="unfinished">Versleutel portemonnee</translation>
+ <translation type="unfinished">Wallet versleutelen</translation>
</message>
<message>
<source>Advanced Options</source>
@@ -1735,8 +1932,7 @@ Indien dit het geval is, gelieve de software te gebruiken waarmee deze portefeui
</message>
<message>
<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">Schakel privésleutels uit voor deze portemonnee. Portommonees met privésleutels uitgeschakeld hebben deze niet en kunnen geen HD seed of geimporteerde privésleutels bevatten.
-Dit is ideaal voor alleen-lezen portommonees.</translation>
+ <translation type="unfinished">Schakel geheime sleutels (private keys) uit voor deze wallet. Wallets met uitgeschakelde geheime sleutels hebben deze niet en kunnen geen HD seed of geimporteerde privésleutels bevatten. Dit is ideaal voor alleen-lezen wallets.</translation>
</message>
<message>
<source>Disable Private Keys</source>
@@ -1744,11 +1940,11 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">Maak een blanco portemonnee. Blanco portemonnees hebben initieel geen privésleutel of scripts. Privésleutels en adressen kunnen later worden geimporteerd of een HD seed kan later ingesteld worden.</translation>
+ <translation type="unfinished">Maak een blanco wallet. Blanco wallets hebben initieel geen privésleutel of scripts. Privésleutels en adressen kunnen worden geimporteerd, of een HD seed kan ingesteld worden, op een later moment.</translation>
</message>
<message>
<source>Make Blank Wallet</source>
- <translation type="unfinished">Maak een lege portemonnee</translation>
+ <translation type="unfinished">Lege wallet aanmaken</translation>
</message>
<message>
<source>Use descriptors for scriptPubKey management</source>
@@ -1756,11 +1952,11 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
</message>
<message>
<source>Descriptor Wallet</source>
- <translation type="unfinished">Descriptor Portemonnee</translation>
+ <translation type="unfinished">Descriptorwallet</translation>
</message>
<message>
<source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
- <translation type="unfinished">Gebruik een extern onderteken device zoals een hardware wallet. Configureer eerst het externe ondertekenaar script in wallet preferences.</translation>
+ <translation type="unfinished">Gebruik een externe signing device zoals een hardware wallet. Configureer eerst het externe signer script in de wallet voorkeuren.</translation>
</message>
<message>
<source>External signer</source>
@@ -1772,7 +1968,7 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
</message>
<message>
<source>Compiled without sqlite support (required for descriptor wallets)</source>
- <translation type="unfinished">Gecompileerd zonder ondersteuning van sqlite (noodzakelijk voor beschrijvende portemonees)</translation>
+ <translation type="unfinished">Gecompileerd zonder sqlite-ondersteuning (nodig voor descriptor wallets)</translation>
</message>
<message>
<source>Compiled without external signing support (required for external signing)</source>
@@ -1824,7 +2020,7 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation type="unfinished">Kon de portemonnee niet openen.</translation>
+ <translation type="unfinished">Kon de wallet niet openen.</translation>
</message>
<message>
<source>New key generation failed.</source>
@@ -1856,13 +2052,26 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(van %1 GB nodig)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n GB opslag ruimte beschikbaar</numerusform>
+ <numerusform>%n GB ruimte beschikbaar</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB nodig voor volledige keten)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(van %n GB nodig)</numerusform>
+ <numerusform>(van %n GB nodig)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n GB nodig voor een volledige keten)</numerusform>
+ <numerusform>(%n GB nodig voor een volledige keten)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1876,8 +2085,8 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>(voldoende om backups van %n dag(en) oud te herstellen)</numerusform>
+ <numerusform>(voldoende om backups van %n dag(en) oud te herstellen)</numerusform>
</translation>
</message>
<message>
@@ -1886,7 +2095,7 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation type="unfinished">De portemonnee wordt ook in deze map opgeslagen.</translation>
+ <translation type="unfinished">De wallet wordt ook in deze map opgeslagen.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
@@ -1909,10 +2118,6 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation type="unfinished">Omdat dit de eerste keer is dat het programma gestart is, kunt u nu kiezen waar %1 de data moet opslaan.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Als u op OK klikt, dan zal %1 beginnen met downloaden en verwerken van de volledige %4 blokketen (%2GB) startend met de eerste transacties in %3 toen %4 initeel werd gestart.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Beperk blockchainopslag tot</translation>
</message>
@@ -1929,6 +2134,10 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation type="unfinished">Deze initiële synchronisatie is heel veeleisend, en kan hardware problemen met uw computer blootleggen die voorheen onopgemerkt bleven. Elke keer dat %1 gebruikt word, zal verdergegaan worden waar gebleven is.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">Als u op OK klikt, dan zal %1 beginnen met downloaden en verwerken van de volledige %4 blokketen (%2 GB) startend met de eerste transacties in %3 toen %4 initeel werd gestart.</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished">Als u gekozen heeft om de blokketenopslag te beperken (pruning), dan moet de historische data nog steeds gedownload en verwerkt worden, maar zal verwijderd worden naderhand om schijf gebruik zo laag mogelijk te houden.</translation>
</message>
@@ -1975,7 +2184,7 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
</message>
<message>
<source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation type="unfinished">Recente transacties zijn mogelijk nog niet zichtbaar. De balans van de portemonnee is daarom mogelijk niet correct. Deze informatie is correct zodra de portemonnee gelijk loopt met het Bitcoin netwerk, zoals onderaan beschreven.</translation>
+ <translation type="unfinished">Recente transacties zijn mogelijk nog niet zichtbaar. De balans van de wallet is daarom mogelijk niet correct. Deze informatie is correct zodra de synchronisatie van de wallet met het Bitcoinnetwerk gereed is, zoals onderaan toegelicht.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
@@ -2007,7 +2216,7 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
</message>
<message>
<source>Estimated time left until synced</source>
- <translation type="unfinished">Geschatte tijd totdat uw portemonnee gelijk loopt met het bitcoin netwerk.</translation>
+ <translation type="unfinished">Geschatte resterende tijd tot synchronisatie is voltooid</translation>
</message>
<message>
<source>Hide</source>
@@ -2021,10 +2230,18 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Onbekend. Blockheaders synchroniseren (%1, %2%)...</translation>
</message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Onbekend. Blockheaders synchroniseren (%1, %2%)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
+ <source>Open bitcoin URI</source>
+ <translation type="unfinished">Open bitcoin-URI</translation>
+ </message>
+ <message>
<source>Paste address from clipboard</source>
<extracomment>Tooltip text for button that allows you to paste an address that is in your clipboard.</extracomment>
<translation type="unfinished">Plak adres vanuit klembord</translation>
@@ -2073,6 +2290,10 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation type="unfinished">Minimaliseren in plaats van de applicatie af te sluiten wanneer het venster is afgesloten. Als deze optie is ingeschakeld, zal de toepassing pas worden afgesloten na het selecteren van Exit in het menu.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Gekozen opties in dit dialoogvenster worden overschreven door de command line:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Open het %1 configuratiebestand van de werkmap.</translation>
</message>
@@ -2161,7 +2382,7 @@ Ongebruikte mempool geheugen is gedeeld voor deze cache.</translation>
</message>
<message>
<source>External Signer (e.g. hardware wallet)</source>
- <translation type="unfinished">Externe ondertekenaar (b.v. een hardware wallet)</translation>
+ <translation type="unfinished">Externe signer (bijv. hardware wallet)</translation>
</message>
<message>
<source>&amp;External signer script path</source>
@@ -2292,10 +2513,6 @@ Ongebruikte mempool geheugen is gedeeld voor deze cache.</translation>
<translation type="unfinished">best overeenkomende "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Gekozen opties in dit dialoogvenster worden overschreven door de command line of in het configuratiebestand:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;Oké</translation>
</message>
@@ -2318,14 +2535,22 @@ Ongebruikte mempool geheugen is gedeeld voor deze cache.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Bevestig reset opties</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Herstart van de client is vereist om veranderingen door te voeren.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Huidige instellingen zullen worden opgeslagen op "%1".</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Applicatie zal worden afgesloten. Wilt u doorgaan?</translation>
</message>
<message>
@@ -2364,6 +2589,13 @@ Ongebruikte mempool geheugen is gedeeld voor deze cache.</translation>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Kon instelling niet lezen "%1", %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2371,7 +2603,7 @@ Ongebruikte mempool geheugen is gedeeld voor deze cache.</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">De weergegeven informatie kan verouderd zijn. Uw portemonnee synchroniseert automatisch met het Bitcoin netwerk nadat een verbinding is gelegd, maar dit proces is nog niet voltooid.</translation>
+ <translation type="unfinished">De weergegeven informatie kan verouderd zijn. Uw wallet synchroniseert automatisch met het Bitcoinnetwerk nadat een verbinding is gelegd, maar dit proces is nog niet voltooid.</translation>
</message>
<message>
<source>Watch-only:</source>
@@ -2478,7 +2710,7 @@ Ongebruikte mempool geheugen is gedeeld voor deze cache.</translation>
</message>
<message>
<source>Cannot sign inputs while wallet is locked.</source>
- <translation type="unfinished">Kan invoer niet ondertekenen terwijl de portemonnee is vergrendeld.</translation>
+ <translation type="unfinished">Kan invoer niet signen terwijl de wallet is vergrendeld.</translation>
</message>
<message>
<source>Could not sign any more inputs.</source>
@@ -2555,15 +2787,15 @@ Ongebruikte mempool geheugen is gedeeld voor deze cache.</translation>
</message>
<message>
<source>(But no wallet is loaded.)</source>
- <translation type="unfinished">(Maar er is geen portemonnee geladen.)</translation>
+ <translation type="unfinished">(Maar er is geen wallet geladen.)</translation>
</message>
<message>
<source>(But this wallet cannot sign transactions.)</source>
- <translation type="unfinished">(Deze wallet kan geen transacties tekenen.)</translation>
+ <translation type="unfinished">(Maar deze wallet kan geen transacties signen.)</translation>
</message>
<message>
<source>(But this wallet does not have the right keys.)</source>
- <translation type="unfinished">(Maar deze portemonnee heeft niet de juiste sleutels.)</translation>
+ <translation type="unfinished">(Maar deze wallet heeft niet de juiste sleutels.)</translation>
</message>
<message>
<source>Transaction is fully signed and ready for broadcast.</source>
@@ -2598,7 +2830,7 @@ Due to widespread security flaws in BIP70 it's strongly recommended that any mer
If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
<translation type="unfinished">Kan betaalverzoek niet verwerken omdat BIP70 niet wordt ondersteund.
Gezien de wijdverspreide beveiligingsproblemen in BIP70 is het sterk aanbevolen om iedere instructie om van wallet te wisselen te negeren.
-Als je deze fout ziet zou je de aanbieder moeten verzoeken om een BIP21 compatibele URI te verstrekken.</translation>
+Als je deze fout ziet zou je de aanbieder moeten verzoeken om een BIP21-compatibele URI te verstrekken.</translation>
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
@@ -2612,6 +2844,11 @@ Als je deze fout ziet zou je de aanbieder moeten verzoeken om een BIP21 compatib
<context>
<name>PeerTableModel</name>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Duur</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Directie</translation>
@@ -2743,7 +2980,7 @@ Als je deze fout ziet zou je de aanbieder moeten verzoeken om een BIP21 compatib
</message>
<message>
<source>Wallet: </source>
- <translation type="unfinished">Portemonnee:</translation>
+ <translation type="unfinished">Wallet:</translation>
</message>
<message>
<source>(none)</source>
@@ -2795,29 +3032,32 @@ Als je deze fout ziet zou je de aanbieder moeten verzoeken om een BIP21 compatib
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Of we adressen doorgeven aan deze peer.</translation>
</message>
<message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Adresrelay</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">Totaal aantal verwerkte adressen, met uitzondering van de adressen die zijn verwijderd vanwege snelheidsbeperking.</translation>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Het totaal aantal van deze peer ontvangen adressen dat verwerkt is (uitgezonderd de door rate-limiting gedropte adressen).</translation>
</message>
<message>
- <source>Addresses Processed</source>
- <translation type="unfinished">Adressen Verwerkt</translation>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Het totaal aantal van deze peer ontvangen adressen dat gedropt (niet verwerkt) is door rate-limiting.</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">Totaal aantal adressen gedaald vanwege snelheidsbeperking.</translation>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Adressen Verwerkt</translation>
</message>
<message>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">Adressen Tarief - Beperkt</translation>
</message>
<message>
@@ -3019,11 +3259,11 @@ Als je deze fout ziet zou je de aanbieder moeten verzoeken om een BIP21 compatib
</message>
<message>
<source>Executing command without any wallet</source>
- <translation type="unfinished">Uitvoeren van commando zonder gebruik van een portemonnee</translation>
+ <translation type="unfinished">Uitvoeren van commando zonder gebruik van een wallet</translation>
</message>
<message>
<source>Executing command using "%1" wallet</source>
- <translation type="unfinished">Uitvoeren van commando met portemonnee "%1"</translation>
+ <translation type="unfinished">Uitvoeren van commando met wallet "%1"</translation>
</message>
<message>
<source>Welcome to the %1 RPC console.
@@ -3040,7 +3280,7 @@ Gebruik %3 en %4 om het lettertype te vergroten of verkleinen.
Type %5 voor een overzicht van beschikbare commando's.
Voor meer informatie over het gebruik van deze console, type %6.
-%7WAARSCHUWING: Er zijn oplichters actief, die gebruikers overhalen om hier commando's te typen, teneinde de inhoud van hun portemonnee te stelen. Gebruik de console niet, zonder de gevolgen van een commando volledig te begrijpen.%8</translation>
+%7WAARSCHUWING: Er zijn oplichters actief, die gebruikers overhalen om hier commando's te typen, teneinde de inhoud van hun wallet te stelen. Gebruik de console niet, zonder de gevolgen van een commando volledig te begrijpen.%8</translation>
</message>
<message>
<source>Executing…</source>
@@ -3164,7 +3404,7 @@ Voor meer informatie over het gebruik van deze console, type %6.
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation type="unfinished">Kon de portemonnee niet openen.</translation>
+ <translation type="unfinished">Kon de wallet niet openen.</translation>
</message>
<message>
<source>Could not generate new %1 address</source>
@@ -3190,10 +3430,6 @@ Voor meer informatie over het gebruik van deze console, type %6.
<translation type="unfinished">Bericht:</translation>
</message>
<message>
- <source>Wallet:</source>
- <translation type="unfinished">Portemonnee:</translation>
- </message>
- <message>
<source>Copy &amp;URI</source>
<translation type="unfinished">Kopieer &amp;URI</translation>
</message>
@@ -3207,7 +3443,7 @@ Voor meer informatie over het gebruik van deze console, type %6.
</message>
<message>
<source>Verify this address on e.g. a hardware wallet screen</source>
- <translation type="unfinished">Verifieer dit adres, bijvoorbeeld op een hardware wallet scherm</translation>
+ <translation type="unfinished">Verifieer dit adres, bijv. op het scherm van een hardware wallet</translation>
</message>
<message>
<source>&amp;Save Image…</source>
@@ -3426,7 +3662,7 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<message>
<source>Sign on device</source>
<extracomment>"device" usually means a hardware wallet.</extracomment>
- <translation type="unfinished">Inlog apparaat</translation>
+ <translation type="unfinished">Onderteken op apparaat</translation>
</message>
<message>
<source>Connect your hardware wallet first.</source>
@@ -3435,7 +3671,7 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<message>
<source>Set external signer script path in Options -&gt; Wallet</source>
<extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Stel een extern onderteken script pad in Opties -&gt; Wallet</translation>
+ <translation type="unfinished">Stel een extern signer script pad in Opties -&gt; Wallet</translation>
</message>
<message>
<source>Cr&amp;eate Unsigned</source>
@@ -3447,7 +3683,7 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
</message>
<message>
<source> from wallet '%1'</source>
- <translation type="unfinished">van portemonnee '%1'</translation>
+ <translation type="unfinished">van wallet '%1'</translation>
</message>
<message>
<source>%1 to '%2'</source>
@@ -3503,8 +3739,7 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<message>
<source>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>
<extracomment>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.</extracomment>
- <translation type="unfinished">Gelieve uw transactie voorstel te controleren. Deze actie zal een Gedeeltelijk Getekende Bitcoin Transactie (PSBT) produceren die je kan opslaan of kopiëre en vervolgends ondertekenen.
-Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</translation>
+ <translation type="unfinished">Controleer aub je transactievoorstel. Dit zal een Gedeeltelijk Getekende Bitcoin Transactie (PSBT) produceren die je kan opslaan of kopiëren en vervolgens ondertekenen met bijv. een offline %1 wallet, of een PSBT-combatibele hardware wallet.</translation>
</message>
<message>
<source>Do you want to create this transaction?</source>
@@ -3514,7 +3749,7 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
<message>
<source>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>
<extracomment>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.</extracomment>
- <translation type="unfinished">Controleer je transactie aub. Je kan deze transactie creëren en verzenden, of een Gedeeltelijk Getekende BitcoinTransactie (PSBT) maken, die je kan opslaan of kopiëren en daarna ondertekenen, bijv. met een offline %1 wallet, of een PSBT-combatibele hardware wallet.</translation>
+ <translation type="unfinished">Controleer aub je transactie. Je kan deze transactie creëren en verzenden, of een Gedeeltelijk Getekende Bitcoin Transactie (PSBT) maken, die je kan opslaan of kopiëren en daarna ondertekenen, bijv. met een offline %1 wallet, of een PSBT-combatibele hardware wallet.</translation>
</message>
<message>
<source>Please, review your transaction.</source>
@@ -3569,15 +3804,11 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Een vergoeding van meer dan %1 wordt beschouwd als een absurd hoge vergoeding.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Betalingsverzoek verlopen.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Geschat om te beginnen met bevestigen binnen %n blok(ken).</numerusform>
+ <numerusform>Geschat om te beginnen met bevestigen binnen %n blok(ken).</numerusform>
</translation>
</message>
<message>
@@ -3594,7 +3825,7 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
</message>
<message>
<source>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>
- <translation type="unfinished">Het wisselgeldadres dat u heeft geselecteerd maakt geen deel uit van deze portemonnee. Een deel of zelfs alle geld in uw portemonnee kan mogelijk naar dit adres worden verzonden. Weet je het zeker?</translation>
+ <translation type="unfinished">Het wisselgeldadres dat u heeft geselecteerd maakt geen onderdeel uit van deze wallet. Enkele of alle saldo's in je wallet zouden naar dit adres kunnen worden verzonden. Weet je het zeker?</translation>
</message>
<message>
<source>(no label)</source>
@@ -3648,14 +3879,6 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
<translation type="unfinished">Bericht:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Dit is een niet-geverifieerd betalingsverzoek.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Dit is een geverifieerd betalingsverzoek.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Vul een label voor dit adres in om het aan de lijst met gebruikte adressen toe te voegen</translation>
</message>
@@ -3663,11 +3886,7 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Een bericht dat werd toegevoegd aan de bitcoin: URI welke wordt opgeslagen met de transactie ter referentie. Opmerking: Dit bericht zal niet worden verzonden over het Bitcoin netwerk.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Betaal Aan:</translation>
- </message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -3783,7 +4002,7 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
</message>
<message>
<source>Wallet unlock was cancelled.</source>
- <translation type="unfinished">Portemonnee ontsleuteling is geannuleerd.</translation>
+ <translation type="unfinished">Wallet ontsleutelen werd geannuleerd.</translation>
</message>
<message>
<source>No error</source>
@@ -3837,30 +4056,32 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">geconflicteerd met een transactie met %1 confirmaties</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/onbevestigd, %1</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/onbevestigd, in mempool</translation>
</message>
<message>
- <source>in memory pool</source>
- <translation type="unfinished">in geheugenpoel</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">niet in geheugenpoel</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/onbevestigd, niet in mempool</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">opgegeven</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/onbevestigd</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 bevestigingen</translation>
</message>
<message>
@@ -3898,8 +4119,8 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>matures in %n more block(s)</numerusform>
+ <numerusform>komt beschikbaar na %n nieuwe blokken</numerusform>
</translation>
</message>
<message>
@@ -4240,13 +4461,13 @@ Vb. een offline %1 portemonee, of een PSBT-combatiebele hardware portemonee.</tr
<source>No wallet has been loaded.
Go to File &gt; Open Wallet to load a wallet.
- OR -</source>
- <translation type="unfinished">Geen portemonee is geladen.
-Ga naar Bestand &gt; Open portemonee om er één te openen.
+ <translation type="unfinished">Er is geen wallet geladen.
+Ga naar Bestand &gt; Wallet openen om een wallet te laden.
- OF -</translation>
</message>
<message>
<source>Create a new wallet</source>
- <translation type="unfinished">Nieuwe wallet creëren</translation>
+ <translation type="unfinished">Nieuwe wallet aanmaken</translation>
</message>
<message>
<source>Error</source>
@@ -4334,7 +4555,7 @@ Ga naar Bestand &gt; Open portemonee om er één te openen.
</message>
<message>
<source>default wallet</source>
- <translation type="unfinished">standaard portemonnee</translation>
+ <translation type="unfinished">standaard wallet</translation>
</message>
</context>
<context>
@@ -4349,12 +4570,12 @@ Ga naar Bestand &gt; Open portemonee om er één te openen.
</message>
<message>
<source>Backup Wallet</source>
- <translation type="unfinished">Portemonnee backuppen</translation>
+ <translation type="unfinished">Wallet backuppen</translation>
</message>
<message>
<source>Wallet Data</source>
<extracomment>Name of the wallet data file format.</extracomment>
- <translation type="unfinished">Portemonneedata</translation>
+ <translation type="unfinished">Walletgegevens</translation>
</message>
<message>
<source>Backup Failed</source>
@@ -4362,7 +4583,7 @@ Ga naar Bestand &gt; Open portemonee om er één te openen.
</message>
<message>
<source>There was an error trying to save the wallet data to %1.</source>
- <translation type="unfinished">Er is een fout opgetreden bij het wegschrijven van de portemonneedata naar %1.</translation>
+ <translation type="unfinished">Er is een fout opgetreden bij het opslaan van de walletgegevens naar %1.</translation>
</message>
<message>
<source>Backup Successful</source>
@@ -4370,7 +4591,7 @@ Ga naar Bestand &gt; Open portemonee om er één te openen.
</message>
<message>
<source>The wallet data was successfully saved to %1.</source>
- <translation type="unfinished">De portemonneedata is succesvol opgeslagen in %1.</translation>
+ <translation type="unfinished">De walletgegevens zijn succesvol opgeslagen in %1.</translation>
</message>
<message>
<source>Cancel</source>
diff --git a/src/qt/locale/bitcoin_no.ts b/src/qt/locale/bitcoin_no.ts
index 569715c814..bfd524d525 100644
--- a/src/qt/locale/bitcoin_no.ts
+++ b/src/qt/locale/bitcoin_no.ts
@@ -152,6 +152,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_pa.ts b/src/qt/locale/bitcoin_pa.ts
new file mode 100644
index 0000000000..e72f6a4bf0
--- /dev/null
+++ b/src/qt/locale/bitcoin_pa.ts
@@ -0,0 +1,448 @@
+<TS version="2.1" language="pa">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation type="unfinished">ਪਤੇ ਜਾਂ ਲੇਬਲ ਦਾ ਸੰਪਾਦਨ ਕਰਨ ਲਈ ਸੱਜਾ-ਕਲਿੱਕ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation type="unfinished">ਨਵਾਂ ਪਤਾ ਬਣਾਓ</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation type="unfinished">&amp;ਨਵਾਂ</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation type="unfinished">ਚà©à¨£à©‡ ਪਤੇ ਦੀ ਸਿਸਟਮ ਦੀ ਚੂੰਢੀ-ਤਖਤੀ 'ਤੇ ਨਕਲ ਲਾਹੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation type="unfinished">&amp;ਨਕਲ ਲਾਹੋ</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation type="unfinished">ਬੰ&amp;ਦ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">ਚà©à¨£à©‡ ਪਤੇ ਨੂੰ ਸੂਚੀ ਵਿੱਚੋਂ ਮਿਟਾਓ</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">ਖੋਜਣ ਲਈ ਪਤਾ ਜਾਂ ਲੇਬਲ ਦਾਖਲ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">ਮੌਜੂਦਾ ਟੈਬ ਵਿੱਚ ਡੇਟਾ ਨੂੰ ਫਾਈਲ ਵਿੱਚ à¨à¨•à¨¸à¨ªà©‹à¨°à¨Ÿ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;ਨਿਰਯਾਤ</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">&amp;ਮਿਟਾਓ</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">ਸਿੱਕੇ ਭੇਜਣ ਲਈ ਪਤਾ ਚà©à¨£à©‹</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">ਸਿੱਕੇ ਪà©à¨°à¨¾à¨ªà¨¤ ਕਰਨ ਲਈ ਪਤਾ ਚà©à¨£à©‹</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">ਇਹ ਭà©à¨—ਤਾਨ ਭੇਜਣ ਲਈ ਤà©à¨¹à¨¾à¨¡à©‡ ਬਿਟਕੋਇਨ ਪਤੇ ਹਨ। ਸਿੱਕੇ ਭੇਜਣ ਤੋਂ ਪਹਿਲਾਂ ਹਮੇਸ਼ਾਂ ਰਕਮ ਅਤੇ ਪà©à¨°à¨¾à¨ªà¨¤ ਕਰਨ ਵਾਲੇ ਪਤੇ ਦੀ ਜਾਂਚ ਕਰੋ।</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation type="unfinished">&amp;ਕਾਪੀ ਪਤਾ</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">&amp;ਲੇਬਲ ਕਾਪੀ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">&amp;ਸੋਧੋ</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation type="unfinished">ਪਤਾ ਸੂਚੀ ਨਿਰਯਾਤ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">ਕਾਮੇ ਨਾਲ ਵੱਖ ਕੀਤੀ ਫਾਈਲ</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">ਨਿਰਯਾਤ ਅਸਫਲ ਰਿਹਾ</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">ਲੇਬਲ</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">ਪਤਾ</translation>
+ </message>
+ </context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ ਡਾਇਲਾਗ</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ ਲਿਖੋ</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation type="unfinished">ਨਵਾਂ ਪਾਸਫਰੇਜ</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation type="unfinished">ਨਵਾਂ ਪਾਸਫਰੇਜ ਦà©à¨¹à¨°à¨¾à¨“</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ ਦਿਖਾਓ</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation type="unfinished">ਵਾਲਿਟ à¨à¨¨à¨•à©à¨°à¨¿à¨ªà¨Ÿ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਨੂੰ ਅਨਲੌਕ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ ਬਦਲੋ</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਇਨਕà©à¨°à¨¿à¨ªà¨¸à¨¼à¨¨ ਦੀ ਪà©à¨¸à¨¼à¨Ÿà©€ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">ਕੀ ਤà©à¨¸à©€à¨‚ ਯਕੀਨੀ ਤੌਰ 'ਤੇ ਆਪਣੇ ਵਾਲਿਟ ਨੂੰ à¨à¨¨à¨•à©à¨°à¨¿à¨ªà¨Ÿ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਨੂੰ à¨à¨¨à¨•à©à¨°à¨¿à¨ªà¨Ÿ ਕੀਤਾ ਗਿਆ</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation type="unfinished">ਇਨਕà©à¨°à¨¿à¨ªà¨Ÿà¨¡ ਹੋਣ ਲਈ ਵਾਲਿਟ</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation type="unfinished">ਤà©à¨¹à¨¾à¨¡à¨¾ ਵਾਲਿਟ à¨à¨¨à¨•à©à¨°à¨¿à¨ªà¨Ÿ ਹੋਣ ਵਾਲਾ ਹੈ।</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation type="unfinished">ਤà©à¨¹à¨¾à¨¡à¨¾ ਵਾਲਿਟ ਹà©à¨£ à¨à¨¨à¨•à©à¨°à¨¿à¨ªà¨Ÿ ਹੋ ਗਿਆ ਹੈ।</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਇਨਕà©à¨°à¨¿à¨ªà¨¸à¨¼à¨¨ ਅਸਫਲ</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">ਸਪਲਾਈ ਕੀਤੇ ਪਾਸਫਰੇਜ਼ ਮੇਲ ਨਹੀਂ ਖਾਂਦੇ।</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਅਨਲੌਕ ਅਸਫਲ ਰਿਹਾ</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਪਾਸਫਰੇਜ ਸਫਲਤਾਪੂਰਵਕ ਬਦਲਿਆ ਗਿਆ।</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished">ਚੇਤਾਵਨੀ: Caps Lock ਕà©à©°à¨œà©€ ਚਾਲੂ ਹੈ!</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">ਇੱਕ ਘਾਤਕ ਗਲਤੀ ਆਈ ਹੈ। %1ਹà©à¨£ ਸà©à¨°à©±à¨–ਿਅਤ ਢੰਗ ਨਾਲ ਜਾਰੀ ਨਹੀਂ ਰਹਿ ਸਕਦਾ ਹੈ ਅਤੇ ਛੱਡ ਦੇਵੇਗਾ।</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">ਅੰਦਰੂਨੀ ਗੜਬੜ</translation>
+ </message>
+ </context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">ਗਲਤੀ: %1</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">ਸੈਟਿੰਗ ਫਾਈਲ ਨੂੰ ਪੜà©à¨¹à¨¨ ਵਿੱਚ ਅਸਫਲ</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">ਸੈਟਿੰਗ ਫਾਈਲ ਲਿਖਣ ਵਿੱਚ ਅਸਫਲ</translation>
+ </message>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>&amp;Overview</source>
+ <translation type="unfinished">&amp;ਓਵਰਵਿਊ</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation type="unfinished">&amp;ਲੈਣ-ਦੇਣ</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation type="unfinished">ਲੈਣ-ਦੇਣ ਦਾ ਇਤਿਹਾਸ ਬà©à¨°à¨¾à¨Šà¨œà¨¼ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation type="unfinished">à¨à¨ªà¨²à©€à¨•à©‡à¨¸à¨¼à¨¨ ਛੱਡੋ</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">ਨਵਾਂ ਵਾਲਿਟ ਬਣਾਓ</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">ਬਟੂਆ: </translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation type="unfinished">ਬਿਟਕੋਇਨ ਪਤੇ 'ਤੇ ਸਿੱਕੇ ਭੇਜੋ</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਨੂੰ ਕਿਸੇ ਹੋਰ ਥਾਂ 'ਤੇ ਬੈਕਅੱਪ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation type="unfinished">ਵਾਲਿਟ ਇਨਕà©à¨°à¨¿à¨ªà¨¸à¨¼à¨¨ ਲਈ ਵਰਤਿਆ ਜਾਣ ਵਾਲਾ ਪਾਸਫਰੇਜ ਬਦਲੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation type="unfinished">&amp;ਭੇਜੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation type="unfinished">&amp;ਪà©à¨°à¨¾à¨ªà¨¤ ਕਰੋ</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;ਵਾਲਿਟ ਇਨਕà©à¨°à¨¿à¨ªà¨Ÿ ਕਰੋ...</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">ਨਿੱਜੀ ਕà©à©°à¨œà©€à¨†à¨‚ ਨੂੰ à¨à¨¨à¨•à©à¨°à¨¿à¨ªà¨Ÿ ਕਰੋ ਜੋ ਤà©à¨¹à¨¾à¨¡à©‡ ਵਾਲਿਟ ਨਾਲ ਸਬੰਧਤ ਹਨ</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;ਬੈਕਅੱਪ ਵਾਲਿਟ…</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">ਪਾਸਫਰੇਜ &amp;ਬਦਲੋ...</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">ਗਲਤੀ: %1</translation>
+ </message>
+ </context>
+<context>
+ <name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(sufficient to restore backups %n day(s) old)</source>
+ <extracomment>Explanatory text on the capability of the current prune target.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>Address</source>
+ <extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
+ <translation type="unfinished">ਪਤਾ</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">ਬਟੂਆ: </translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">ਲੇਬਲ</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">ਲੇਬਲ</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">ਕਾਮੇ ਨਾਲ ਵੱਖ ਕੀਤੀ ਫਾਈਲ</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">ਲੇਬਲ</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">ਪਤਾ</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">ਨਿਰਯਾਤ ਅਸਫਲ ਰਿਹਾ</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">ਨਵਾਂ ਵਾਲਿਟ ਬਣਾਓ</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;ਨਿਰਯਾਤ</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">ਮੌਜੂਦਾ ਟੈਬ ਵਿੱਚ ਡੇਟਾ ਨੂੰ ਫਾਈਲ ਵਿੱਚ à¨à¨•à¨¸à¨ªà©‹à¨°à¨Ÿ ਕਰੋ</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts
index 99247f1579..d25f00c415 100644
--- a/src/qt/locale/bitcoin_pam.ts
+++ b/src/qt/locale/bitcoin_pam.ts
@@ -427,6 +427,24 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -745,10 +763,6 @@
<source>Message:</source>
<translation type="unfinished">Mensayi:</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Ibayad kang:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -865,10 +879,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/ali me-kumpirma</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 kumpirmasion</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts
index 6fc1f2e032..215cbf055c 100644
--- a/src/qt/locale/bitcoin_pl.ts
+++ b/src/qt/locale/bitcoin_pl.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">Kliknij prawy przycisk myszy, aby edytować adres lub etykietę</translation>
+ <translation type="unfinished">Kliknij prawym przyciskiem myszy, aby edytować adres lub etykietę</translation>
</message>
<message>
<source>Create a new address</source>
@@ -43,7 +43,7 @@
</message>
<message>
<source>&amp;Delete</source>
- <translation type="unfinished">Usuń</translation>
+ <translation type="unfinished">&amp;Usuń</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
@@ -59,7 +59,7 @@
</message>
<message>
<source>Sending addresses</source>
- <translation type="unfinished">Wysyłające adresy</translation>
+ <translation type="unfinished">&amp;Adresy wysyłania8f0451c0-ec7d-4357-a370-eff72fb0685f</translation>
</message>
<message>
<source>Receiving addresses</source>
@@ -103,7 +103,7 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Exporting Failed</source>
- <translation type="unfinished"> Eksportowanie nie powiodło się </translation>
+ <translation type="unfinished">Eksportowanie nie powiodło się </translation>
</message>
</context>
<context>
@@ -125,7 +125,7 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
- <translation type="unfinished"> Okienko Hasła </translation>
+ <translation type="unfinished">Okienko Hasła </translation>
</message>
<message>
<source>Enter passphrase</source>
@@ -157,7 +157,7 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Change passphrase</source>
- <translation type="unfinished"> Zmień hasło </translation>
+ <translation type="unfinished">Zmień hasło </translation>
</message>
<message>
<source>Confirm wallet encryption</source>
@@ -185,11 +185,11 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation type="unfinished">Zwróć uwagę, że zaszyfrowanie portfela nie zabezpieczy się w pełni przed kradzieżą przez malware jakie może zainfekować twój komputer. </translation>
+ <translation type="unfinished">Pamiętaj, że zaszyfrowanie portfela nie pomoże w zapobiegnięciu kradzieży twoich bitcoinów jeśli komputer zostanie zainfekowany przez złośliwe oprogramowanie.</translation>
</message>
<message>
<source>Wallet to be encrypted</source>
- <translation type="unfinished"> Portfel do zaszyfrowania </translation>
+ <translation type="unfinished">Portfel do zaszyfrowania </translation>
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
@@ -246,8 +246,16 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Plik ustawień 1%1 może być uszkodzony lub nieprawidłowy</translation>
+ </message>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">BÅ‚Ä…d zapisu do portfela</translation>
+ </message>
+ <message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <translation type="unfinished">Wystąpił krytyczny błąd. %1 nie może dalej bezpiecznie pracować i zostanie zakończony.</translation>
+ <translation type="unfinished">Wystąpił fatalny błąd. %1 nie może być kontynuowany i zostanie zakończony.</translation>
</message>
<message>
<source>Internal error</source>
@@ -261,6 +269,16 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Przywrócić ustawienia domyślne czy zrezygnować bez dokonywania zmian?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Wystąpił krytyczny błąd. Upewnij się, że plik ustawień można nadpisać lub uruchom klienta z parametrem -nosettings.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Błąd: Określony folder danych "%1" nie istnieje.</translation>
</message>
@@ -303,11 +321,31 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Wyjściowy</translation>
</message>
<message>
+ <source>Full Relay</source>
+ <extracomment>Peer connection type that relays all network information.</extracomment>
+ <translation type="unfinished">Pełny Przekaźnik</translation>
+ </message>
+ <message>
+ <source>Block Relay</source>
+ <extracomment>Peer connection type that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">Przekaźnik Blokowy</translation>
+ </message>
+ <message>
<source>Manual</source>
<extracomment>Peer connection type established manually through one of several methods.</extracomment>
<translation type="unfinished">Ręczny</translation>
</message>
<message>
+ <source>Feeler</source>
+ <extracomment>Short-lived peer connection type that tests the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Szczelinomierz</translation>
+ </message>
+ <message>
+ <source>Address Fetch</source>
+ <extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
+ <translation type="unfinished">Pobieranie adresu</translation>
+ </message>
+ <message>
<source>None</source>
<translation type="unfinished">Żaden</translation>
</message>
@@ -371,6 +409,14 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Nie udało się odczytać pliku ustawień</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Nie udało się zapisać pliku ustawień</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">Deweloperzy %s</translation>
</message>
@@ -383,10 +429,18 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">-maxtxfee ma ustawioną badzo dużą wartość! Tak wysokie opłaty mogą być zapłacone w jednej transakcji.</translation>
</message>
<message>
+ <source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
+ <translation type="unfinished">Nie można zmienić wersji portfela z wersji %ina wersje %i. Wersja portfela pozostaje niezmieniona.</translation>
+ </message>
+ <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation type="unfinished">Nie można uzyskać blokady na katalogu z danymi %s. %s najprawdopodobniej jest już uruchomiony.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Nie można zaktualizować portfela dzielonego innego niż HD z wersji 1%i do wersji 1%i bez aktualizacji w celu obsługi wstępnie podzielonej puli kluczy. Użyj wersji 1%i lub nie określono wersji.</translation>
+ </message>
+ <message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation type="unfinished">Rozprowadzane na licencji MIT, zobacz dołączony plik %s lub %s</translation>
</message>
@@ -395,18 +449,54 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Błąd odczytu %s! Wszystkie klucze zostały odczytane poprawnie, ale może brakować danych transakcji lub wpisów w książce adresowej, lub mogą one być nieprawidłowe.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Błąd: Nasłuchiwanie połączeń przychodzących nie powiodło się (nasłuch zwrócił błąd %s)</translation>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Błąd odczytu 1%s! Może brakować danych transakcji lub mogą być one nieprawidłowe. Ponowne skanowanie portfela.</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
+ <translation type="unfinished">BÅ‚Ä…d: rekord formatu pliku zrzutu jest nieprawidÅ‚owy. Otrzymano „1%sâ€, oczekiwany „formatâ€.</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile identifier record is incorrect. Got "%s", expected "%s".</source>
+ <translation type="unfinished">BÅ‚Ä…d: rekord identyfikatora pliku zrzutu jest nieprawidÅ‚owy. Otrzymano „1%sâ€, oczekiwano „1%sâ€.</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
+ <translation type="unfinished">Błąd: wersja pliku zrzutu nie jest obsługiwana. Ta wersja bitcoin-wallet obsługuje tylko pliki zrzutów w wersji 1. Mam plik zrzutu w wersji 1%s</translation>
+ </message>
+ <message>
+ <source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
+ <translation type="unfinished">BÅ‚Ä…d: starsze portfele obsÅ‚ugujÄ… tylko typy adresów „legacyâ€, „p2sh-segwit†i „bech32â€</translation>
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Estymacja opłat nieudana. Domyślna opłata jest wyłączona. Poczekaj kilka bloków lub włącz -fallbackfee.</translation>
</message>
<message>
+ <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">Plik 1%s już istnieje. Jeśli jesteś pewien, że tego chcesz, najpierw usuń to z drogi.</translation>
+ </message>
+ <message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation type="unfinished">Niewłaściwa ilość dla -maxtxfee=&lt;ilość&gt;: '%s' (musi wynosić przynajmniej minimalną wielkość %s aby zapobiec utknięciu transakcji)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Nieprawidłowy lub uszkodzony plik peers.dat (1%s). Jeśli uważasz, że to błąd, zgłoś go do 1%s. Jako obejście, możesz przenieść plik (1%s) z drogi (zmień nazwę, przenieś lub usuń), aby przy następnym uruchomieniu utworzyć nowy.</translation>
+ </message>
+ <message>
+ <source>No dump file provided. To use createfromdump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">Nie dostarczono pliku zrzutu. Aby użyć funkcji createfromdump, należy podać -dumpfile=1.</translation>
+ </message>
+ <message>
+ <source>No dump file provided. To use dump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">Nie dostarczono pliku zrzutu. Aby użyć funkcji createfromdump, należy podać -dumpfile=1.</translation>
+ </message>
+ <message>
+ <source>No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
+ <translation type="unfinished">Nie dostarczono pliku zrzutu. Aby użyć funkcji createfromdump, należy podać -dumpfile=1.</translation>
+ </message>
+ <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation type="unfinished">Proszę sprawdzić czy data i czas na Twoim komputerze są poprawne! Jeżeli ustawienia zegara będą złe, %s nie będzie działał prawidłowo.</translation>
</message>
@@ -431,6 +521,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Baza bloków zawiera blok, który wydaje się pochodzić z przyszłości. Może to wynikać z nieprawidłowego ustawienia daty i godziny Twojego komputera. Bazę danych bloków dobuduj tylko, jeśli masz pewność, że data i godzina twojego komputera są poprawne</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">Baza danych indeksu bloku zawiera odziedziczony „txindexâ€. Aby wyczyÅ›cić zajÄ™te miejsce na dysku, uruchom peÅ‚nÄ… indeksacjÄ™, w przeciwnym razie zignoruj ten bÅ‚Ä…d. Ten komunikat o bÅ‚Ä™dzie nie zostanie ponownie wyÅ›wietlony.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">Zbyt niska kwota transakcji do wysłania po odjęciu opłaty</translation>
</message>
@@ -463,6 +557,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Nie można przetworzyć bloków. Konieczne będzie przebudowanie bazy danych za pomocą -reindex-chainstate.</translation>
</message>
<message>
+ <source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
+ <translation type="unfinished">Podano nieznany typ pliku portfela "%s". Proszę podać jeden z "bdb" lub "sqlite".</translation>
+ </message>
+ <message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
<translation type="unfinished">Uwaga: Wykryto klucze prywatne w portfelu [%s] który ma wyłączone klucze prywatne</translation>
</message>
@@ -499,6 +597,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Nie mogę zapisać do katalogu danych '%s'; sprawdź uprawnienia.</translation>
</message>
<message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Zmiana nazwy nieprawidłowego pliku peers.dat nie powiodła się. Przenieś go lub usuń i spróbuj ponownie.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Ustawienie konfiguracyjne %s działa na sieć %s tylko, jeżeli jest w sekcji [%s].</translation>
</message>
@@ -531,6 +633,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Wczytywanie zakończone</translation>
</message>
<message>
+ <source>Error creating %s</source>
+ <translation type="unfinished">BÅ‚Ä…d podczas tworzenia %s</translation>
+ </message>
+ <message>
<source>Error initializing block database</source>
<translation type="unfinished">Błąd inicjowania bazy danych bloków</translation>
</message>
@@ -567,18 +673,34 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Błąd odczytu z bazy danych, wyłączam się.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Błąd ładowania bazy bloków</translation>
+ <source>Error reading next record from wallet database</source>
+ <translation type="unfinished">BÅ‚Ä…d odczytu kolejnego rekordu z bazy danych portfela</translation>
</message>
<message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Błąd: zbyt mało miejsca na dysku dla %s</translation>
</message>
<message>
+ <source>Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
+ <translation type="unfinished">BÅ‚Ä…d: Plik zrzutu suma kontrolna nie pasuje. Obliczone %s, spodziewane %s</translation>
+ </message>
+ <message>
<source>Error: Keypool ran out, please call keypoolrefill first</source>
<translation type="unfinished">Błąd: Pula kluczy jest pusta, odwołaj się do puli kluczy.</translation>
</message>
<message>
+ <source>Error: Missing checksum</source>
+ <translation type="unfinished">BÅ‚ad: Brak suma kontroly</translation>
+ </message>
+ <message>
+ <source>Error: No %s addresses available.</source>
+ <translation type="unfinished">Błąd: %s adres nie dostępny</translation>
+ </message>
+ <message>
+ <source>Error: Unable to write record to new wallet</source>
+ <translation type="unfinished">Błąd: Wpisanie rekordu do nowego portfela jest niemożliwe</translation>
+ </message>
+ <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">Próba nasłuchiwania na jakimkolwiek porcie nie powiodła się. Użyj -listen=0 jeśli tego chcesz.</translation>
</message>
@@ -599,6 +721,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Ignorowanie duplikatu -wallet %s</translation>
</message>
<message>
+ <source>Importing…</source>
+ <translation type="unfinished">Importowanie...</translation>
+ </message>
+ <message>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
<translation type="unfinished">Nieprawidłowy lub brak bloku genezy. Błędny folder_danych dla sieci?</translation>
</message>
@@ -643,12 +769,32 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Nieprawidłowa maska sieci określona w -whitelist: '%s'</translation>
</message>
<message>
+ <source>Loading P2P addresses…</source>
+ <translation type="unfinished">Åadowanie adresów P2P...</translation>
+ </message>
+ <message>
+ <source>Loading banlist…</source>
+ <translation type="unfinished">Åadowanie listy zablokowanych...</translation>
+ </message>
+ <message>
+ <source>Loading block index…</source>
+ <translation type="unfinished">Åadowanie indeksu bloku...</translation>
+ </message>
+ <message>
+ <source>Loading wallet…</source>
+ <translation type="unfinished">Åadowanie portfela...</translation>
+ </message>
+ <message>
+ <source>Missing amount</source>
+ <translation type="unfinished">BrakujÄ…ca kwota</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Musisz określić port z -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Żaden serwer proxy nie jest ustawiony. Użyj -proxy=&lt;ip&gt; lub -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Brak dostępnych adresów</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -667,6 +813,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Zmniejszanie -maxconnections z %d do %d z powodu ograniczeń systemu.</translation>
</message>
<message>
+ <source>Rescanning…</source>
+ <translation type="unfinished">Ponowne skanowanie...</translation>
+ </message>
+ <message>
<source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
<translation type="unfinished">SQLiteDatabase: nie powiodło się wykonanie instrukcji weryfikującej bazę danych: %s</translation>
</message>
@@ -708,6 +858,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</translation>
</message>
<message>
+ <source>Starting network threads…</source>
+ <translation type="unfinished">Startowanie wątków sieciowych...</translation>
+ </message>
+ <message>
<source>The source code is available from %s.</source>
<translation type="unfinished">Kod źródłowy dostępny jest z %s.</translation>
</message>
@@ -772,6 +926,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Nie można wygenerować kluczy</translation>
</message>
<message>
+ <source>Unable to open %s for writing</source>
+ <translation type="unfinished">Nie można otworzyć %s w celu zapisu</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">Uruchomienie serwera HTTP nie powiodło się. Zobacz dziennik debugowania, aby uzyskać więcej szczegółów.</translation>
</message>
@@ -796,14 +954,18 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Nieobsługiwana kategoria rejestrowania %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Aktualizowanie bazy danych UTXO</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Komentarz User Agent (%s) zawiera niebezpieczne znaki.</translation>
</message>
<message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">Weryfikowanie bloków...</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)…</source>
+ <translation type="unfinished">Weryfikowanie porfela(li)...</translation>
+ </message>
+ <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation type="unfinished">Portfel wymaga przepisania: zrestartuj %s aby ukończyć</translation>
</message>
@@ -859,6 +1021,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Stwórz nowy portfel</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">Z&amp;minimalizuj</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Portfel:</translation>
</message>
@@ -897,13 +1063,17 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
- <translation type="unfinished">Zaszyfruj portf&amp;el...</translation>
+ <translation type="unfinished">&amp;Zaszyfruj portfel</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
<translation type="unfinished">Szyfruj klucze prywatne, które są w twoim portfelu</translation>
</message>
<message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">Utwórz kopię zapasową portfela...</translation>
+ </message>
+ <message>
<source>&amp;Change Passphrase…</source>
<translation type="unfinished">&amp;Zmień hasło...</translation>
</message>
@@ -913,7 +1083,7 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Podpisz wiadomości swoim adresem, aby udowodnić jego posiadanie</translation>
+ <translation type="unfinished">Podpisz wiadomości swoim adresem aby udowodnić jego posiadanie</translation>
</message>
<message>
<source>&amp;Verify message…</source>
@@ -924,6 +1094,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Zweryfikuj wiadomość, aby upewnić się, że została podpisana podanym adresem bitcoinowym.</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">Wczytaj PSBT z pliku...</translation>
+ </message>
+ <message>
<source>Open &amp;URI…</source>
<translation type="unfinished">Otwórz &amp;URI...</translation>
</message>
@@ -956,8 +1130,32 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Pasek zakładek</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Synchronizuję nagłówki (%1%)…</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Synchronizacja z sieciÄ…...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Indeksowanie bloków...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Przetwarzanie bloków...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Ponowne indeksowanie bloków...</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">ÅÄ…czenie z uczestnikami sieci...</translation>
+ </message>
+ <message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation type="unfinished">Żądaj płatności (generuje kod QR oraz bitcoinowe URI)</translation>
+ <translation type="unfinished">Zażądaj płatności (wygeneruj QE code i bitcoin: URI)</translation>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
@@ -974,9 +1172,9 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>Przetworzono %n blok historii transakcji.</numerusform>
+ <numerusform>Przetworzono 1%n bloków historii transakcji.</numerusform>
+ <numerusform>Przetworzono 1%n bloków historii transakcji.</numerusform>
</translation>
</message>
<message>
@@ -984,6 +1182,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">%1 za</translation>
</message>
<message>
+ <source>Catching up…</source>
+ <translation type="unfinished">SynchronizujÄ™...</translation>
+ </message>
+ <message>
<source>Last received block was generated %1 ago.</source>
<translation type="unfinished">Ostatni otrzymany blok został wygenerowany %1 temu.</translation>
</message>
@@ -1012,6 +1214,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Załaduj częściowo podpisaną transakcję Bitcoin</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">Wczytaj PSBT ze schowka...</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Załaduj częściowo podpisaną transakcję Bitcoin ze schowka</translation>
</message>
@@ -1048,6 +1254,16 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Zamknij portfel</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Przywróć Portfel…</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Przywróć portfel z pliku kopii zapasowej</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Zamknij wszystkie portfele</translation>
</message>
@@ -1072,6 +1288,26 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Brak dostępnych portfeli</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Informacje portfela</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Załaduj kopię zapasową portfela</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Przywróć portfel</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nazwa portfela</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Okno</translation>
</message>
@@ -1087,6 +1323,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<source>%1 client</source>
<translation type="unfinished">%1 klient</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Ukryj</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1097,6 +1337,26 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</translation>
</message>
<message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Kliknij po więcej funkcji.</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">Wyświetl połączenia</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">Wyłącz aktywność sieciową</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">Włącz aktywność sieciową</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">BÅ‚Ä…d: %1</translation>
</message>
@@ -1170,7 +1430,7 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Original message:</source>
- <translation type="unfinished">Wiadomość oryginalna:</translation>
+ <translation type="unfinished">Orginalna wiadomość:</translation>
</message>
</context>
<context>
@@ -1212,11 +1472,11 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Change:</source>
- <translation type="unfinished">Reszta:</translation>
+ <translation type="unfinished">Zmiana:</translation>
</message>
<message>
<source>(un)select all</source>
- <translation type="unfinished">Zaznacz/Odznacz wszystko</translation>
+ <translation type="unfinished">zaznacz/odznacz wszytsko</translation>
</message>
<message>
<source>Tree mode</source>
@@ -1244,17 +1504,41 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Confirmations</source>
- <translation type="unfinished">Potwierdzenia</translation>
+ <translation type="unfinished">Potwierdzenie</translation>
</message>
<message>
<source>Confirmed</source>
- <translation type="unfinished">Potwierdzony</translation>
+ <translation type="unfinished">Potwerdzone</translation>
</message>
<message>
<source>Copy amount</source>
+ <translation type="unfinished">Kopiuj kwote</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">Kopiuj adres</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiuj etykietÄ™</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
<translation type="unfinished">Kopiuj kwotÄ™</translation>
</message>
<message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Skopiuj &amp;ID transakcji oraz wyjściowy indeks</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">Zabl&amp;okuj niewydane</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">Odblok&amp;uj niewydane</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Skopiuj ilość</translation>
</message>
@@ -1316,31 +1600,48 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<message>
<source>Create Wallet</source>
<extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
- <translation type="unfinished">Stwórz portfel</translation>
+ <translation type="unfinished">Stwórz potrfel</translation>
</message>
<message>
<source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
<extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
- <translation type="unfinished">Otwieranie portfela &lt;b&gt;%1&lt;/b&gt;...</translation>
+ <translation type="unfinished">Tworzenie portfela &lt;b&gt;%1&lt;/b&gt;...</translation>
</message>
<message>
<source>Create wallet failed</source>
- <translation type="unfinished">Tworzenie portfela nieudane</translation>
+ <translation type="unfinished">Nieudane tworzenie potrfela</translation>
</message>
<message>
<source>Create wallet warning</source>
<translation type="unfinished">Ostrzeżenie przy tworzeniu portfela</translation>
</message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Nie można wyświetlić sygnatariuszy</translation>
+ </message>
</context>
<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished"> Åaduj portfele</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">Åadowanie portfeli...</translation>
+ </message>
+</context>
+<context>
<name>OpenWalletActivity</name>
<message>
<source>Open wallet failed</source>
- <translation type="unfinished">Otwarcie portfela nie powiodło się</translation>
+ <translation type="unfinished">Otworzenie portfela nie powiodło się</translation>
</message>
<message>
<source>Open wallet warning</source>
- <translation type="unfinished">Ostrzeżenie przy otwieraniu portfela</translation>
+ <translation type="unfinished">Ostrzeżenie przy otworzeniu potrfela</translation>
</message>
<message>
<source>default wallet</source>
@@ -1351,6 +1652,19 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">Otwórz Portfel</translation>
</message>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">Otwieranie portfela &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
+<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Przywróć portfel</translation>
+ </message>
</context>
<context>
<name>WalletController</name>
@@ -1379,7 +1693,7 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<name>CreateWalletDialog</name>
<message>
<source>Create Wallet</source>
- <translation type="unfinished">Stwórz portfel</translation>
+ <translation type="unfinished">Stwórz potrfel</translation>
</message>
<message>
<source>Wallet Name</source>
@@ -1426,6 +1740,14 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Portfel deskryptora</translation>
</message>
<message>
+ <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
+ <translation type="unfinished">Użyj zewnętrznego urządzenia podpisującego, takiego jak portfel sprzętowy. Najpierw skonfiguruj zewnętrzny skrypt podpisujący w preferencjach portfela.</translation>
+ </message>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">Zewnętrzny sygnatariusz</translation>
+ </message>
+ <message>
<source>Create</source>
<translation type="unfinished">Stwórz</translation>
</message>
@@ -1433,7 +1755,12 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<source>Compiled without sqlite support (required for descriptor wallets)</source>
<translation type="unfinished">Skompilowano bez wsparcia sqlite (wymaganego dla deskryptorów potfeli)</translation>
</message>
- </context>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Skompilowany bez obsługi podpisywania zewnętrznego (wymagany do podpisywania zewnętrzengo)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -1514,6 +1841,30 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Co najmniej %1 GB danych, zostanie zapisane w tym katalogu, dane te będą przyrastały w czasie.</translation>
@@ -1560,14 +1911,18 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Ponieważ jest to pierwsze uruchomienie programu, możesz wybrać gdzie %1 będzie przechowywał swoje dane.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Gdy naciśniesz OK, %1 zacznie się pobieranie i przetwarzanie całego %4 łańcucha bloków (%2GB) zaczynając od najwcześniejszych transakcji w %3 gdy %4 został uruchomiony.</translation>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">Ogranicz przechowywanie łańcucha bloków do</translation>
</message>
<message>
<source>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>
<translation type="unfinished">Wyłączenie tej opcji spowoduje konieczność pobrania całego łańcucha bloków. Szybciej jest najpierw pobrać cały łańcuch a następnie go przyciąć (prune). Wyłącza niektóre zaawansowane funkcje.</translation>
</message>
<message>
+ <source> GB</source>
+ <translation type="unfinished">GB</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">Wstępna synchronizacja jest bardzo wymagająca i może ujawnić wcześniej niezauważone problemy sprzętowe. Za każdym uruchomieniem %1 pobieranie będzie kontynuowane od miejsca w którym zostało zatrzymane.</translation>
</message>
@@ -1602,6 +1957,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1 siÄ™ zamyka...</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation type="unfinished">Nie wyłączaj komputera dopóki to okno nie zniknie.</translation>
</message>
@@ -1625,6 +1984,14 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Pozostało bloków</translation>
</message>
<message>
+ <source>Unknown…</source>
+ <translation type="unfinished">Nieznany...</translation>
+ </message>
+ <message>
+ <source>calculating…</source>
+ <translation type="unfinished">obliczanie...</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation type="unfinished">Czas ostatniego bloku</translation>
</message>
@@ -1652,6 +2019,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
<translation type="unfinished">%1 jest w trakcie synchronizacji. Trwa pobieranie i weryfikacja nagłówków oraz bloków z sieci w celu uzyskania aktualnego stanu łańcucha.</translation>
</message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">nieznany, Synchronizowanie nagłówków (1%1, 2%2%)</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1684,6 +2055,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Uruchamiaj %1 wraz z zalogowaniem do &amp;systemu</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Włączenie czyszczenia znacznie zmniejsza ilość miejsca na dysku wymaganego do przechowywania transakcji. Wszystkie bloki są nadal w pełni zweryfikowane. Przywrócenie tego ustawienia wymaga ponownego pobrania całego łańcucha bloków.</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation type="unfinished">Wielkość bufora bazy &amp;danych</translation>
</message>
@@ -1732,14 +2107,44 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Cofnięcie tego ustawienia wymaga ponownego załadowania całego łańcucha bloków.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">Maksymalny rozmiar pamięci podręcznej bazy danych. Większa pamięć podręczna może przyczynić się do szybszej synchronizacji, po której korzyści są mniej widoczne w większości przypadków użycia. Zmniejszenie rozmiaru pamięci podręcznej zmniejszy zużycie pamięci. Nieużywana pamięć mempool jest współdzielona dla tej pamięci podręcznej.</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Ustaw liczbę wątków weryfikacji skryptu. Wartości ujemne odpowiadają liczbie rdzeni, które chcesz pozostawić systemowi.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = automatycznie, &lt;0 = zostaw tyle wolnych rdzeni)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Umożliwia tobie lub narzędziu innej firmy komunikowanie się z węzłem za pomocą wiersza polecenia i poleceń JSON-RPC.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">WÅ‚Ä…cz serwer R&amp;PC</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">Portfel</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Czy ustawić opłatę odejmowaną od kwoty jako domyślną, czy nie.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Domyślnie odejmij opłatę od kwoty</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">Ekspert</translation>
</message>
@@ -1756,6 +2161,28 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Wydaj niepotwierdzonÄ… re&amp;sztÄ™</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">WÅ‚Ä…cz ustawienia &amp;PSBT</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Czy wyświetlać opcje PSBT.</translation>
+ </message>
+ <message>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">Zewnętrzny sygnatariusz (np. portfel sprzętowy) </translation>
+ </message>
+ <message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">&amp;Ścieżka zewnętrznego skryptu podpisującego</translation>
+ </message>
+ <message>
+ <source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
+ <translation type="unfinished">Pełna ścieżka do skryptu zgodnego z Bitcoin Core (np. C:\Downloads\hwi.exe lub /Users/you/Downloads/hwi.py). Uwaga: złośliwe oprogramowanie może ukraść Twoje monety!</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">Automatycznie otwiera port klienta Bitcoin na routerze. Ta opcja dzieła tylko jeśli twój router wspiera UPnP i jest ono włączone.</translation>
</message>
@@ -1764,6 +2191,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Mapuj port używając &amp;UPnP</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Automatycznie otwiera port klienta Bitcoin w routerze. Działa jedynie wtedy, gdy router wspiera NAT-PMP i usługa ta jest włączona. Zewnętrzny port może być losowy.</translation>
+ </message>
+ <message>
<source>Map port using NA&amp;T-PMP</source>
<translation type="unfinished">Mapuj port przy użyciu NA&amp;T-PMP</translation>
</message>
@@ -1840,6 +2271,14 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Wybierz podział jednostki pokazywany w interfejsie oraz podczas wysyłania monet</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Adresy URL stron trzecich (np. eksplorator bloków), które pojawiają się na karcie transakcji jako pozycje menu kontekstowego. %s w adresie URL jest zastępowane hashem transakcji. Wiele adresów URL jest oddzielonych pionową kreską |.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;Adresy URL transakcji stron trzecich</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Wybierz pokazywanie lub nie funkcji kontroli monet.</translation>
</message>
@@ -1852,14 +2291,23 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Użyj oddzielnego proxy SOCKS&amp;5 aby osiągnąć węzły w ukrytych usługach Tor:</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Opcje ustawione w tym oknie sÄ… nadpisane przez liniÄ™ komend lub plik konfiguracyjny:</translation>
+ <source>Monospaced font in the Overview tab:</source>
+ <translation type="unfinished">Czcionka o stałej szerokości w zakładce Przegląd:</translation>
+ </message>
+ <message>
+ <source>closest matching "%1"</source>
+ <translation type="unfinished">najbliższy pasujący "%1"</translation>
</message>
<message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Anuluj</translation>
</message>
<message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Skompilowany bez obsługi podpisywania zewnętrznego (wymagany do podpisywania zewnętrzengo)</translation>
+ </message>
+ <message>
<source>default</source>
<translation type="unfinished">domyślny</translation>
</message>
@@ -1869,14 +2317,17 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Potwierdź reset ustawień</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Wymagany restart programu, aby uaktywnić zmiany.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Program zostanie wyłączony. Czy chcesz kontynuować?</translation>
</message>
<message>
@@ -1890,6 +2341,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Plik konfiguracyjny jest używany celem zdefiniowania zaawansowanych opcji nadpisujących ustawienia aplikacji okienkowej (GUI). Parametry zdefiniowane z poziomu linii poleceń nadpisują parametry określone w tym pliku.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">Kontynuuj</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">Anuluj</translation>
</message>
@@ -2004,6 +2459,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Kopiuj do schowka</translation>
</message>
<message>
+ <source>Save…</source>
+ <translation type="unfinished">Zapisz...</translation>
+ </message>
+ <message>
<source>Close</source>
<translation type="unfinished">Zamknij</translation>
</message>
@@ -2016,6 +2475,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Nie udało się podpisać transakcji: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Nie można podpisywać danych wejściowych, gdy portfel jest zablokowany.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">Nie udało się podpisać więcej wejść.</translation>
</message>
@@ -2044,6 +2507,11 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Zapisz dane transakcji</translation>
</message>
<message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">Częściowo podpisana transakcja (binarna)</translation>
+ </message>
+ <message>
<source>PSBT saved to disk.</source>
<translation type="unfinished">PSBT zapisane na dysk.</translation>
</message>
@@ -2080,6 +2548,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Transakcja ciÄ…gle oczekuje na podpis(y).</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Ale żaden portfel nie jest załadowany.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Ale ten portfel nie może podipisać transakcji.)</translation>
</message>
@@ -2115,6 +2587,14 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">'bitcoin://' nie jest poprawnym URI. Użyj 'bitcoin:'.</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.
+Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
+If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation type="unfinished">Nie można przetworzyć żądanie zapłaty poniewasz BIP70 nie jest obsługiwany.
+Ze względu na wady bezpieczeństwa w BIP70 jest zalecane ignorować wszelkich instrukcji od sprzedawcę dotyczących zmiany portfela.
+Jeśli pojawia się ten błąd, poproś sprzedawcę o podanie URI zgodnego z BIP21. </translation>
+ </message>
+ <message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
<translation type="unfinished">Nie można przeanalizować identyfikatora URI! Może to być spowodowane nieważnym adresem Bitcoin lub nieprawidłowymi parametrami URI.</translation>
</message>
@@ -2174,6 +2654,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<context>
<name>QRImageWidget</name>
<message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">Zapi&amp;sz Obraz...</translation>
+ </message>
+ <message>
<source>&amp;Copy Image</source>
<translation type="unfinished">&amp;Kopiuj obraz</translation>
</message>
@@ -2306,6 +2790,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Zsynchronizowane bloki</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Ostatnia Transakcja</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">Zmapowany autonomiczny system (ang. asmap) używany do dywersyfikacji wyboru węzłów.</translation>
</message>
@@ -2314,6 +2802,26 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Zmapowany autonomiczny system (ang. asmap)</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Czy przekazujemy adresy do tego peera.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Adres Przekaźnika</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Przetworzone Adresy</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Wskaźnik-Ograniczeń Adresów</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Aplikacja kliencka</translation>
</message>
@@ -2342,6 +2850,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Uprawnienia</translation>
</message>
<message>
+ <source>Direction/Type</source>
+ <translation type="unfinished">Kierunek/Rodzaj</translation>
+ </message>
+ <message>
<source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
<translation type="unfinished">Protokół sieciowy używany przez ten węzeł: IPv4, IPv6, Onion, I2P, lub CJDNS.</translation>
</message>
@@ -2350,6 +2862,22 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Usługi</translation>
</message>
<message>
+ <source>Whether the peer requested us to relay transactions.</source>
+ <translation type="unfinished">Czy peer poprosił nas o przekazanie transakcji.</translation>
+ </message>
+ <message>
+ <source>Wants Tx Relay</source>
+ <translation type="unfinished">Chce przekaźnik Tx</translation>
+ </message>
+ <message>
+ <source>High bandwidth BIP152 compact block relay: %1</source>
+ <translation type="unfinished">Kompaktowy przekaźnik blokowy BIP152 o dużej przepustowości: 1 %1</translation>
+ </message>
+ <message>
+ <source>High Bandwidth</source>
+ <translation type="unfinished">Wysoka Przepustowość</translation>
+ </message>
+ <message>
<source>Connection Time</source>
<translation type="unfinished">Czas połączenia</translation>
</message>
@@ -2358,6 +2886,11 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Ostatni Blok</translation>
</message>
<message>
+ <source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
+ <extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
+ <translation type="unfinished">Czas, który upłynął od otrzymania nowej transakcji przyjętej do naszej pamięci od tego partnera.</translation>
+ </message>
+ <message>
<source>Last Send</source>
<translation type="unfinished">Ostatnio wysłano</translation>
</message>
@@ -2427,6 +2960,48 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Przychodzące: zainicjowane przez węzeł</translation>
</message>
<message>
+ <source>Outbound Full Relay: default</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</extracomment>
+ <translation type="unfinished">Pełny przekaźnik wychodzący: domyślnie</translation>
+ </message>
+ <message>
+ <source>Outbound Block Relay: does not relay transactions or addresses</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">Outbound Block Relay: nie przekazuje transakcji ani adresów</translation>
+ </message>
+ <message>
+ <source>Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Outbound Manual: dodano przy użyciu opcji konfiguracyjnych RPC 1%1 lub 2%2/3%3</translation>
+ </message>
+ <message>
+ <source>Outbound Feeler: short-lived, for testing addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Outbound Feeler: krótkotrwały, do testowania adresów</translation>
+ </message>
+ <message>
+ <source>Outbound Address Fetch: short-lived, for soliciting addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</extracomment>
+ <translation type="unfinished">Pobieranie adresu wychodzącego: krótkotrwałe, do pozyskiwania adresów</translation>
+ </message>
+ <message>
+ <source>we selected the peer for high bandwidth relay</source>
+ <translation type="unfinished">wybraliśmy peera dla przekaźnika o dużej przepustowości</translation>
+ </message>
+ <message>
+ <source>the peer selected us for high bandwidth relay</source>
+ <translation type="unfinished">peer wybrał nas do przekaźnika o dużej przepustowości</translation>
+ </message>
+ <message>
+ <source>no high bandwidth relay selected</source>
+ <translation type="unfinished">nie wybrano przekaźnika o dużej przepustowości</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">Kopiuj adres</translation>
+ </message>
+ <message>
<source>&amp;Disconnect</source>
<translation type="unfinished">&amp;Rozłącz</translation>
</message>
@@ -2435,6 +3010,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">1 &amp;godzina</translation>
</message>
<message>
+ <source>1 d&amp;ay</source>
+ <translation type="unfinished">1 dzień</translation>
+ </message>
+ <message>
<source>1 &amp;week</source>
<translation type="unfinished">1 &amp;tydzień</translation>
</message>
@@ -2443,6 +3022,11 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">1 &amp;rok</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">Skopiuj IP/MaskÄ™ Sieci</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">&amp;Odblokuj</translation>
</message>
@@ -2459,6 +3043,11 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Wykonuję komendę używając portfela "%1"</translation>
</message>
<message>
+ <source>Executing…</source>
+ <extracomment>A console message indicating an entered command is currently being executed.</extracomment>
+ <translation type="unfinished">WykonujÄ™...</translation>
+ </message>
+ <message>
<source>via %1</source>
<translation type="unfinished">przez %1</translation>
</message>
@@ -2566,6 +3155,22 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Kopiuj &amp;URI</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">Kopiuj adres</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiuj etykietÄ™</translation>
+ </message>
+ <message>
+ <source>Copy &amp;message</source>
+ <translation type="unfinished">Skopiuj wiado&amp;mość</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopiuj kwotÄ™</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">Nie można było odblokować portfela.</translation>
</message>
@@ -2577,6 +3182,10 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>Request payment to …</source>
+ <translation type="unfinished">Żądaj płatności do ...</translation>
+ </message>
+ <message>
<source>Address:</source>
<translation type="unfinished">Adres:</translation>
</message>
@@ -2605,6 +3214,18 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
<translation type="unfinished">Kopiuj &amp;adres</translation>
</message>
<message>
+ <source>&amp;Verify</source>
+ <translation type="unfinished">Zweryfikuj</translation>
+ </message>
+ <message>
+ <source>Verify this address on e.g. a hardware wallet screen</source>
+ <translation type="unfinished">Zweryfikuj ten adres np. na ekranie portfela sprzętowego</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">Zapi&amp;sz Obraz...</translation>
+ </message>
+ <message>
<source>Payment information</source>
<translation type="unfinished">Informacje o płatności</translation>
</message>
@@ -2684,7 +3305,7 @@ Podpisywanie jest możliwe tylko z adresami typu 'legacy'.</translation>
</message>
<message>
<source>Change:</source>
- <translation type="unfinished">Reszta:</translation>
+ <translation type="unfinished">Zmiana:</translation>
</message>
<message>
<source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
@@ -2736,14 +3357,30 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
<translation type="unfinished">Wyczyść wszystkie pola formularza.</translation>
</message>
<message>
+ <source>Inputs…</source>
+ <translation type="unfinished">Wejścia…</translation>
+ </message>
+ <message>
<source>Dust:</source>
<translation type="unfinished">Pył:</translation>
</message>
<message>
+ <source>Choose…</source>
+ <translation type="unfinished">Wybierz...</translation>
+ </message>
+ <message>
<source>Hide transaction fee settings</source>
<translation type="unfinished">Ukryj ustawienia opłat transakcyjnych</translation>
</message>
<message>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation type="unfinished">Określ niestandardową opłatę za kB (1000 bajtów) wirtualnego rozmiaru transakcji.
+
+Uwaga: Ponieważ opłata jest naliczana za każdy bajt, opłata "100 satoshi za kB" w przypadku transakcji o wielkości 500 bajtów (połowa 1 kB) ostatecznie da opłatę w wysokości tylko 50 satoshi.</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">Gdy ilość transakcji jest mniejsza niż ilość miejsca w bloku, górnicy i węzły przekazujące wymagają minimalnej opłaty. Zapłata tylko tej wartości jest dopuszczalna, lecz może skutkować transakcją która nigdy nie zostanie potwierdzona w sytuacji, gdy ilość transakcji przekroczy przepustowość sieci.</translation>
</message>
@@ -2752,6 +3389,10 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
<translation type="unfinished">Zbyt niska opłata może spowodować, że transakcja nigdy nie zostanie zatwierdzona (przeczytaj podpowiedź)</translation>
</message>
<message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks…)</source>
+ <translation type="unfinished">(Sprytne opłaty nie są jeszcze zainicjowane. Trwa to zwykle kilka bloków...)</translation>
+ </message>
+ <message>
<source>Confirmation time target:</source>
<translation type="unfinished">Docelowy czas potwierdzenia:</translation>
</message>
@@ -2785,7 +3426,7 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
</message>
<message>
<source>Copy amount</source>
- <translation type="unfinished">Kopiuj kwotÄ™</translation>
+ <translation type="unfinished">Kopiuj kwote</translation>
</message>
<message>
<source>Copy fee</source>
@@ -2809,7 +3450,21 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
</message>
<message>
<source>%1 (%2 blocks)</source>
- <translation type="unfinished">%1 (%2 bloków)</translation>
+ <translation type="unfinished">%1 (%2 bloków)github.com </translation>
+ </message>
+ <message>
+ <source>Sign on device</source>
+ <extracomment>"device" usually means a hardware wallet.</extracomment>
+ <translation type="unfinished">Podpisz na urzÄ…dzeniu</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">Najpierw podłącz swój sprzętowy portfel.</translation>
+ </message>
+ <message>
+ <source>Set external signer script path in Options -&gt; Wallet</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Ustaw ścieżkę zewnętrznego skryptu podpisującego w Opcje -&gt; Portfel</translation>
</message>
<message>
<source>Cr&amp;eate Unsigned</source>
@@ -2825,25 +3480,48 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
</message>
<message>
<source>%1 to '%2'</source>
- <translation type="unfinished">%1 do '%2'</translation>
+ <translation type="unfinished">%1 do '%2'8f0451c0-ec7d-4357-a370-eff72fb0685f</translation>
</message>
<message>
<source>%1 to %2</source>
<translation type="unfinished">%1 do %2</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details…"</source>
+ <translation type="unfinished">Aby przejrzeć listę odbiorców kliknij "Pokaż szczegóły..."</translation>
+ </message>
+ <message>
<source>Sign failed</source>
<translation type="unfinished">Podpisywanie nie powiodło się.</translation>
</message>
<message>
+ <source>External signer not found</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Nie znaleziono zewnętrznego sygnatariusza </translation>
+ </message>
+ <message>
+ <source>External signer failure</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Błąd zewnętrznego sygnatariusza </translation>
+ </message>
+ <message>
<source>Save Transaction Data</source>
<translation type="unfinished">Zapisz dane transakcji</translation>
</message>
<message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">Częściowo podpisana transakcja (binarna)</translation>
+ </message>
+ <message>
<source>PSBT saved</source>
<translation type="unfinished">Zapisano PSBT</translation>
</message>
<message>
+ <source>External balance:</source>
+ <translation type="unfinished">Zewnętrzny balans:</translation>
+ </message>
+ <message>
<source>or</source>
<translation type="unfinished">lub</translation>
</message>
@@ -2857,6 +3535,16 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
<translation type="unfinished">Proszę przejrzeć propozycję transakcji. Zostanie utworzona częściowo podpisana transakcja (ang. PSBT), którą można skopiować, a następnie podpisać np. offline z portfelem %1 lub z innym portfelem zgodnym z PSBT.</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Czy chcesz utworzyć tę transakcję?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Proszę przejrzeć propozycję transakcji. Zostanie utworzona częściowo podpisana transakcja (ang. PSBT), którą można skopiować, a następnie podpisać np. offline z portfelem %1 lub z innym portfelem zgodnym z PSBT.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">ProszÄ™, zweryfikuj swojÄ… transakcjÄ™.</translation>
@@ -2909,10 +3597,6 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Opłata wyższa niż %1 jest uznawana za absurdalnie dużą.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Żądanie płatności upłynęło.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2993,14 +3677,6 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
<translation type="unfinished">Wiadomość:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">To żądanie zapłaty nie zostało zweryfikowane.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">To żądanie zapłaty jest zweryfikowane.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Wprowadź etykietę dla tego adresu by dodać go do listy użytych adresów</translation>
</message>
@@ -3008,14 +3684,6 @@ Korzystanie z opłaty domyślnej może skutkować wysłaniem transakcji, która
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Wiadomość, która została dołączona do URI bitcoin:, która będzie przechowywana wraz z transakcją w celach informacyjnych. Uwaga: Ta wiadomość nie będzie rozsyłana w sieci Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Wpłać do:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Notatka:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3178,35 +3846,31 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<source>(press q to shutdown and continue later)</source>
<translation type="unfinished">(naciśnij q by zamknąć i kontynuować póżniej)</translation>
</message>
- </context>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">wciśnij q aby wyłączyć</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">sprzeczny z transakcją posiadającą %1 potwierdzeń</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/niezatwierdzone, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">w obszarze pamięci</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">nie w obszarze pamięci</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">porzucone</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/niezatwierdzone</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 potwierdzeń</translation>
</message>
<message>
@@ -3507,6 +4171,55 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation type="unfinished">Minimalna kwota</translation>
</message>
<message>
+ <source>Range…</source>
+ <translation type="unfinished">Zakres...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">Kopiuj adres</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Kopiuj etykietÄ™</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopiuj kwotÄ™</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">Skopiuj &amp;ID transakcji</translation>
+ </message>
+ <message>
+ <source>Copy &amp;raw transaction</source>
+ <translation type="unfinished">Kopiuj &amp;raw transakcje</translation>
+ </message>
+ <message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">Skopiuj pełne &amp;detale transakcji</translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">Wyświetl &amp;szczegóły transakcji</translation>
+ </message>
+ <message>
+ <source>Increase transaction &amp;fee</source>
+ <translation type="unfinished">Zwiększ opłatę transakcji</translation>
+ </message>
+ <message>
+ <source>A&amp;bandon transaction</source>
+ <translation type="unfinished">Porzuć transakcję</translation>
+ </message>
+ <message>
+ <source>&amp;Edit address label</source>
+ <translation type="unfinished">Wy&amp;edytuj adres etykiety</translation>
+ </message>
+ <message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Wyświetl w %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Eksport historii transakcji</translation>
</message>
@@ -3517,7 +4230,7 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
</message>
<message>
<source>Confirmed</source>
- <translation type="unfinished">Potwierdzony</translation>
+ <translation type="unfinished">Potwerdzone</translation>
</message>
<message>
<source>Watch-only</source>
@@ -3541,7 +4254,7 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
</message>
<message>
<source>Exporting Failed</source>
- <translation type="unfinished"> Eksportowanie nie powiodło się </translation>
+ <translation type="unfinished">Eksportowanie nie powiodło się </translation>
</message>
<message>
<source>There was an error trying to save the transaction history to %1.</source>
@@ -3635,6 +4348,10 @@ Przejdź do Plik &gt; Otwórz Portfel aby wgrać portfel.
<translation type="unfinished">Nowa opłata:</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Ostrzeżenie: Może to spowodować uiszczenie dodatkowej opłaty poprzez zmniejszenie zmian wyjść lub dodanie danych wejściowych, jeśli jest to konieczne. Może dodać nowe wyjście zmiany, jeśli jeszcze nie istnieje. Te zmiany mogą potencjalnie spowodować utratę prywatności.</translation>
+ </message>
+ <message>
<source>Confirm fee bump</source>
<translation type="unfinished">Potwierdź zwiększenie opłaty</translation>
</message>
@@ -3655,6 +4372,10 @@ Przejdź do Plik &gt; Otwórz Portfel aby wgrać portfel.
<translation type="unfinished">Nie można zatwierdzić transakcji</translation>
</message>
<message>
+ <source>Can't display address</source>
+ <translation type="unfinished">Nie można wyświetlić adresu</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">domyślny portfel</translation>
</message>
@@ -3674,6 +4395,11 @@ Przejdź do Plik &gt; Otwórz Portfel aby wgrać portfel.
<translation type="unfinished">Kopia zapasowa portfela</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Informacje portfela</translation>
+ </message>
+ <message>
<source>Backup Failed</source>
<translation type="unfinished">Nie udało się wykonać kopii zapasowej</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt.ts b/src/qt/locale/bitcoin_pt.ts
index 4e141c66a2..80e8d9a566 100644
--- a/src/qt/locale/bitcoin_pt.ts
+++ b/src/qt/locale/bitcoin_pt.ts
@@ -165,7 +165,7 @@ Assinar só é possível com endereços do tipo "legado".</translation>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished">Aviso: se encriptar a sua carteira e perder a sua frase de segurnça, &lt;b&gt;PERDERà TODOS OS SEUS BITCOINS&lt;/b&gt;!</translation>
+ <translation type="unfinished">Aviso: se encriptar a sua carteira e perder a sua frase de segurança, &lt;b&gt;PERDERà TODAS AS SUAS BITCOINS&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -331,6 +331,11 @@ Assinar só é possível com endereços do tipo "legado".</translation>
<translation type="unfinished">Retransmissão de Blocos</translation>
</message>
<message>
+ <source>Feeler</source>
+ <extracomment>Short-lived peer connection type that tests the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Antena</translation>
+ </message>
+ <message>
<source>Address Fetch</source>
<extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
<translation type="unfinished">Procura de endreços</translation>
@@ -433,10 +438,6 @@ Assinar só é possível com endereços do tipo "legado".</translation>
<translation type="unfinished">Erro: Esta versão do bitcoin-wallet apenas suporta arquivos de despejo na versão 1. (Versão atual: %s)</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Erro: a escuta de ligações de entrada falhou (escuta devolveu o erro %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Falha na estimativa de taxa. A taxa alternativa de recurso está desativada. Espere alguns blocos ou ative -fallbackfee.</translation>
</message>
@@ -630,10 +631,6 @@ deve ser fornecido.</translation>
<translation type="unfinished">Erro ao ler o registo seguinte da base de dados da carteira</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Erro ao atualizar a base de dados do estado da cadeia (chainstate)</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Erro: espaço em disco demasiado baixo para %s</translation>
</message>
@@ -754,12 +751,16 @@ deve ser fornecido.</translation>
<translation type="unfinished">A carregar a carteira…</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Falta a quantia</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Necessário especificar uma porta com -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Sem servidor de proxy especificado. Use -proxy=&lt;ip&gt; ou -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Sem endereços disponíveis</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -770,10 +771,6 @@ deve ser fornecido.</translation>
<translation type="unfinished">A redução não pode ser configurada com um valor negativo.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Modo de poda é incompatível com -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">O modo de redução é incompatível com -txindex.</translation>
</message>
@@ -884,6 +881,10 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">A transação dever pelo menos um destinatário</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Transação precisa de uma mudança de endereço, mas nós não a podemos gerar.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Transação grande demais</translation>
</message>
@@ -940,10 +941,6 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">Categoria de registos desconhecida %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">A atualizar a base de dados UTXO</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Comentário no User Agent (%s) contém caracteres inseguros.</translation>
</message>
@@ -1267,6 +1264,16 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">Sem carteiras disponíveis</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Dados da carteira</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nome da Carteira</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Janela</translation>
</message>
@@ -1282,6 +1289,14 @@ A pasta de blocos especificados "%s" não existe.</translation>
<source>%1 client</source>
<translation type="unfinished">Cliente %1</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">Ocultar</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">Mo&amp;strar</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1569,7 +1584,7 @@ A pasta de blocos especificados "%s" não existe.</translation>
<source>Can't list signers</source>
<translation type="unfinished">Não é possível listar signatários</translation>
</message>
-</context>
+ </context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1783,13 +1798,26 @@ A pasta de blocos especificados "%s" não existe.</translation>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(de %1 GB necessários)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(1%1 GB necessários para a blockchain completa)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1836,10 +1864,6 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">Sendo esta a primeira vez que o programa é iniciado, poderá escolher onde o %1 irá guardar os seus dados.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Quando clicar OK, %1 vai começar a descarregar e processar a cadeia de blocos %4 completa (%2GB) começando com as transações mais antigas em %3 quando a %4 foi inicialmente lançada.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Limitar o tamanho da blockchain para</translation>
</message>
@@ -1948,7 +1972,7 @@ A pasta de blocos especificados "%s" não existe.</translation>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Desconhecido. A sincronizar cabeçalhos (%1, %2%)...</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2041,14 +2065,39 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">Tamanho máximo da cache da base de dados. Uma cache maior pode contribuir para uma sincronização mais rápida, a partir do qual os benefícios são menos visíveis. Ao baixar o tamanho da cache irá diminuir a utilização de memória. Memória da mempool não usada será partilhada com esta cache.</translation>
</message>
<message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Define o número de threads do script de verificação. Valores negativos correspondem ao número de núcleos que deseja deixar livres para o sistema.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = automático, &lt;0 = deixar essa quantidade de núcleos livre)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Isto permite-lhe comunicar a si ou a ferramentas de terceiros com o nó através da linha de comandos e comandos JSON-RPC.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">Ativar servidor R&amp;PC</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">C&amp;arteira</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Mostrar a quantia com a taxa já subtraída, por padrão.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Subtrair &amp;taxa da quantia por padrão</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">Técnicos</translation>
</message>
@@ -2065,6 +2114,16 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">&amp;Gastar troco não confirmado</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Ativar os controlos &amp;PSBT</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Mostrar os controlos PSBT.</translation>
+ </message>
+ <message>
<source>External Signer (e.g. hardware wallet)</source>
<translation type="unfinished">Signatário externo (ex: carteira física)</translation>
</message>
@@ -2085,6 +2144,10 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">Mapear porta usando &amp;UPnP</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Abrir a porta do cliente bitcoin automaticamente no seu router. Isto só funciona se o seu router suportar NAT-PMP e este se encontrar ligado. A porta externa poderá ser aleatória.</translation>
+ </message>
+ <message>
<source>Map port using NA&amp;T-PMP</source>
<translation type="unfinished">Mapear porta usando &amp;NAT-PMP</translation>
</message>
@@ -2165,6 +2228,14 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">Escolha a unidade da subdivisão predefinida para ser mostrada na interface e quando enviar as moedas.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">URLs de outrem (ex. um explorador de blocos) que aparece no separador de transações como itens do menu de contexto. %s do URL é substituído pela hash de transação. Múltiplos URLs são separados pela barra vertical I.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">URLs de transação de &amp;terceiros</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Escolha se deve mostrar as funcionalidades de controlo de moedas ou não.</translation>
</message>
@@ -2181,8 +2252,12 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">Fonte no painel de visualização:</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">As opções nesta janela são substituídas pela linha de comandos ou no ficheiro de configuração:</translation>
+ <source>embedded "%1"</source>
+ <translation type="unfinished">embutido "%1"</translation>
+ </message>
+ <message>
+ <source>closest matching "%1"</source>
+ <translation type="unfinished">resultado mais aproximado "%1"</translation>
</message>
<message>
<source>&amp;Cancel</source>
@@ -2203,14 +2278,17 @@ A pasta de blocos especificados "%s" não existe.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirme a reposição das opções</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">É necessário reiniciar o cliente para ativar as alterações.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">O cliente será desligado. Deseja continuar?</translation>
</message>
<message>
@@ -2224,6 +2302,10 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">O ficheiro de configuração é usado para especificar opções de utilizador avançado, que sobrescrevem as configurações do interface gráfico. Adicionalmente, qualquer opção da linha de comandos vai sobrescrever este ficheiro de configuração.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">Continuar</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">Cancelar</translation>
</message>
@@ -2354,6 +2436,10 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation type="unfinished">Falha ao assinar transação: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Não é possível assinar entradas enquanto a carteira está trancada.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">Não pode assinar mais nenhuma entrada.</translation>
</message>
@@ -2428,6 +2514,10 @@ ID transação: %1</translation>
<translation type="unfinished">Transação continua precisando de assinatura(s).</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Mas nenhuma carteira está carregada)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Porém esta carteira não pode assinar transações.)</translation>
</message>
@@ -2463,6 +2553,14 @@ ID transação: %1</translation>
<translation type="unfinished">'bitcoin://' não é um URI válido. Utilize 'bitcoin:'.</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.
+Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
+If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation type="unfinished">Não é possível processar o pagamento pedido porque o BIP70 não é suportado.
+Devido a falhas de segurança no BIP70, é recomendado que todas as instruçÅes ao comerciante para mudar de carteiras sejam ignorada.
+Se está a receber este erro, deverá pedir ao comerciante para fornecer um URI compatível com BIP21.</translation>
+ </message>
+ <message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
<translation type="unfinished">URI não foi lido corretamente! Isto pode ser causado por um endereço Bitcoin inválido ou por parâmetros URI malformados.</translation>
</message>
@@ -2663,6 +2761,10 @@ ID transação: %1</translation>
<translation type="unfinished">Blocos Sincronizados</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Última Transação</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">O sistema autónomo mapeado usado para diversificar a seleção de pares.</translation>
</message>
@@ -2671,6 +2773,26 @@ ID transação: %1</translation>
<translation type="unfinished">Mapeado como</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Endereços são retransmitidos para este nó.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Retransmissão de endereços</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Endereços Processados</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Endereços com limite de taxa</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation type="unfinished">Janela do nó</translation>
</message>
@@ -3245,7 +3367,7 @@ Para mais informação acerca da utilização desta consola, escreva %6.
</message>
<message>
<source>Copy amount</source>
- <translation type="unfinished">Copiar quantia</translation>
+ <translation type="unfinished">Copiar valor</translation>
</message>
<message>
<source>Copy fee</source>
@@ -3281,6 +3403,11 @@ Para mais informação acerca da utilização desta consola, escreva %6.
<translation type="unfinished">Por favor conecte a sua wallet física primeiro.</translation>
</message>
<message>
+ <source>Set external signer script path in Options -&gt; Wallet</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Defina o caminho do script do assinante externo em Opções -&gt; Carteira</translation>
+ </message>
+ <message>
<source>Cr&amp;eate Unsigned</source>
<translation type="unfinished">Criar não assinado</translation>
</message>
@@ -3401,10 +3528,6 @@ Para mais informação acerca da utilização desta consola, escreva %6.
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Uma taxa superior a %1 é considerada uma taxa altamente absurda.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Pedido de pagamento expirado.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3484,14 +3607,6 @@ Para mais informação acerca da utilização desta consola, escreva %6.
<translation type="unfinished">Mensagem:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Pedido de pagamento não autenticado.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Pedido de pagamento autenticado.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduza uma etiqueta para este endereço para o adicionar à sua lista de endereços usados</translation>
</message>
@@ -3499,14 +3614,6 @@ Para mais informação acerca da utilização desta consola, escreva %6.
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Uma mensagem que estava anexada ao URI bitcoin: que será armazenada com a transação para sua referência. Nota: Esta mensagem não será enviada através da rede Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pagar a:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Memorando:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3663,33 +3770,32 @@ Para mais informação acerca da utilização desta consola, escreva %6.
</message>
</context>
<context>
+ <name>SplashScreen</name>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">Carregue q para desligar</translation>
+ </message>
+</context>
+<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">incompatível com uma transação com %1 confirmações</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/não confirmada, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">no banco de memória</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">não está no banco de memória</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abandonada</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/não confirmada</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 confirmações</translation>
</message>
<message>
@@ -4013,10 +4119,23 @@ Para mais informação acerca da utilização desta consola, escreva %6.
<translation type="unfinished">Copiar Id. da transação</translation>
</message>
<message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">Copie toda a transação &amp;details</translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">Mo&amp;strar detalhes da transação</translation>
+ </message>
+ <message>
<source>&amp;Edit address label</source>
<translation type="unfinished">&amp;Editar etiqueta do endereço</translation>
</message>
<message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Mostrar em %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Exportar Histórico de Transações</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts
index c531a992a2..024652c5a6 100644
--- a/src/qt/locale/bitcoin_pt_BR.ts
+++ b/src/qt/locale/bitcoin_pt_BR.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">Clique com o botão direito para editar endereço ou etiqueta</translation>
+ <translation type="unfinished">Clique com o botão direito para editar o endereço ou a etiqueta</translation>
</message>
<message>
<source>Create a new address</source>
@@ -35,7 +35,7 @@
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation type="unfinished">Exportar os dados do separador atual para um ficheiro</translation>
+ <translation type="unfinished">Exportar os dados do separador atual para um arquivo</translation>
</message>
<message>
<source>&amp;Export</source>
@@ -43,7 +43,7 @@
</message>
<message>
<source>&amp;Delete</source>
- <translation type="unfinished">&amp;Excluir</translation>
+ <translation type="unfinished">E&amp;xcluir</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
@@ -246,6 +246,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Arquivos de configurações %1 podem estar corrompidos ou inválidos</translation>
+ </message>
+ <message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
<translation type="unfinished">Aconteceu um erro fatal. %1 não pode continuar com segurança e será fechado.</translation>
</message>
@@ -295,6 +299,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Informe um endereço Bitcoin (ex: %1)</translation>
</message>
<message>
+ <source>Ctrl+W</source>
+ <translation type="unfinished">Control+W</translation>
+ </message>
+ <message>
<source>Inbound</source>
<extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
<translation type="unfinished">Entrada</translation>
@@ -311,36 +319,36 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n segundo</numerusform>
+ <numerusform>%n segundos</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n minuto</numerusform>
+ <numerusform>%n minutos</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n hora</numerusform>
+ <numerusform>%n horas</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n dia</numerusform>
+ <numerusform>%n dias</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n semana</numerusform>
+ <numerusform>%n semanas</numerusform>
</translation>
</message>
<message>
@@ -350,8 +358,8 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n ano</numerusform>
+ <numerusform>%nanos </numerusform>
</translation>
</message>
</context>
@@ -390,8 +398,8 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Erro ao ler arquivo %s! Todas as chaves privadas foram lidas corretamente, mas os dados de transação ou o livro de endereços podem estar faltando ou incorretos.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Erro: A escuta de conexões de entrada falhou (vincular retornou erro %s)</translation>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Erro ao ler %s! Dados de transações podem estar incorretos ou faltando. Reescaneando a carteira.</translation>
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
@@ -402,6 +410,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Valor inválido para -maxtxfee=&lt;valor&gt;: '%s' (precisa ser pelo menos a taxa de minrelay de %s para prevenir que a transação nunca seja confirmada)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">O arquivo peers.dat (%s) está corrompido ou inválido. Se você acredita se tratar de um bug, por favor reporte para %s. Como solução, você pode mover, renomear ou deletar (%s) para um novo ser criado na próxima inicialização</translation>
+ </message>
+ <message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
<translation type="unfinished">Mais de um endereço onion associado é fornecido. Usando %s para automaticamento criar serviço onion Tor.</translation>
</message>
@@ -418,6 +430,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Configuração de prune abaixo do mínimo de %d MiB.Por gentileza use um número mais alto.</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">O modo Prune é incompatível com a opção "-reindex-chainstate". Ao invés disso utilize "-reindex".</translation>
+ </message>
+ <message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished">Prune: A ultima sincronização da carteira foi além dos dados podados. Você precisa usar -reindex (fazer o download de toda a blockchain novamente no caso de nós com prune)</translation>
</message>
@@ -430,6 +446,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">O banco de dados de blocos contém um bloco que parece ser do futuro. Isso pode ser devido à data e hora do seu computador estarem configuradas incorretamente. Apenas reconstrua o banco de dados de blocos se você estiver certo de que a data e hora de seu computador estão corretas.</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">O banco de dados de índices de bloco contém um 'txindex' antigo. Faça um -reindex completo para liberar espaço em disco, se desejar. Este erro não será exibido novamente.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">A quantia da transação é muito pequena para mandar depois de deduzida a taxa</translation>
</message>
@@ -462,6 +482,14 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Não é possível reproduzir blocos. Você precisará reconstruir o banco de dados usando -reindex-chainstate.</translation>
</message>
<message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Formato de banco de dados incompatível na chainstate. Por favor reinicie com a opção "-reindex-chainstate". Isto irá recriar o banco de dados da chainstate.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Carteira criada com sucesso. As carteiras antigas estão sendo descontinuadas e o suporte para a criação de abertura de carteiras antigas será removido no futuro.</translation>
+ </message>
+ <message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
<translation type="unfinished">Aviso: Chaves privadas detectadas na carteira {%s} com chaves privadas desativadas</translation>
</message>
@@ -494,6 +522,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Não foi possível encontrar o endereço de -%s: '%s'</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">Não é possível definir -forcednsseed para true quando -dnsseed for false.</translation>
+ </message>
+ <message>
<source>Cannot set -peerblockfilters without -blockfilterindex.</source>
<translation type="unfinished">Não pode definir -peerblockfilters sem -blockfilterindex.</translation>
</message>
@@ -502,6 +534,98 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Não foi possível escrever no diretório '%s': verifique as permissões.</translation>
</message>
<message>
+ <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">O processo de atualização do -txindex iniciado por uma versão anterior não foi concluído. Reinicie com a versão antiga ou faça um -reindex completo.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s solicitou abertura da porta %u. Esta porta é considerada "ruim" e é improvável que outros usuários do Bitcoin Core conseguirão se conectar. Veja doc/p2p-bad-ports.md para detalhes e uma lista completa.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">a opção "-reindex-chainstate" não é compatível com "-blockfilterindex". Por favor, desabilite temporariamente a opção "blockfilterindex" enquanto utilizar a opção "-reindex-chainstate", ou troque "-reindex-chainstate" por "-reindex" para recriar completamente todos os índices. </translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">a opção "-reindex-chainstate" não é compatível com a opção "-coinstatsindex". Por favor desative temporariamente a opção "coinstatsindex" enquanto estiver utilizando "-reindex-chainstate", ou troque "-reindex-chainstate" por "-reindex" para recriar completamente todos os índices.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">a opção "-reindex-chainstate" não é compatível com a opção "-coinstatsindex". Por favor desative temporariamente a opção "coinstatsindex" enquanto estiver utilizando "-reindex-chainstate", ou troque "-reindex-chainstate" por "-reindex" para recriar completamente todos os índices.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Assumed-valid: a ultima sincronização da carteira foi além dos blocos de dados disponíveis. Você deve aguardar que a validação em segundo plano baixe mais blocos. </translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Não é possível fornecer conexões específicas e ter addrman procurando conexões ao mesmo tempo.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Erro ao abrir %s: Carteira com assinador externo. Não foi compilado suporte para assinadores externos</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Erro: Os dados do livro de endereços da carteira não puderam ser identificados por pertencerem a carteiras migradas</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">Erro: Descritores duplicados criados durante a migração. Sua carteira pode estar corrompida.</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Erro: A transação %s na carteira não pôde ser identificada por pertencer a carteiras migradas</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">Erro: Impossível produzir descritores para esta carteira antiga. Certifique-se que a carteira foi desbloqueada antes</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Impossível renomear o arquivo peers.dat (inválido). Por favor mova-o ou delete-o e tente novamente.</translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">Opções incompatíveis: "-dnsseed=1" foi explicitamente específicada, mas "-onlynet" proíbe conexões para IPv4/IPv6</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">As conexões de saída foram restringidas a rede Tor (-onlynet-onion) mas o proxy para alcançar a rede Tor foi explicitamente proibido: "-onion=0"</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">As conexões de saída foram restringidas a rede Tor (-onlynet=onion) mas o proxy para acessar a rede Tor não foi fornecido: nenhuma opção "-proxy", "-onion" ou "-listenonion" foi fornecida</translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">Descriptor não reconhecido foi encontrado. Carregando carteira %s
+
+A carteira pode ter sido criada em uma versão mais nova.
+Por favor tente atualizar o software para a última versão.
+</translation>
+ </message>
+ <message>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished">Categoria especificada no nível de log não suportada "-loglevel=%s". Esperado "-loglevel=&lt;category&gt;:&lt;loglevel&gt;. Categorias validas: %s. Níveis de log válidos: %s.</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+Impossível limpar a falha de migração</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Impossível restaurar backup da carteira.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">A configuração %s somente é aplicada na rede %s quando na sessão [%s].</translation>
</message>
@@ -566,18 +690,58 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Erro ao ler o banco de dados. Encerrando.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Erro ao atualizar banco de dados do chainstate</translation>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">Erro: impossível adicionar tx apenas-visualização para carteira apenas-visualização</translation>
+ </message>
+ <message>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">Erro: Impossível excluir transações apenas-visualização </translation>
</message>
<message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Erro: Espaço em disco menor que %s</translation>
</message>
<message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">Erro: Falha ao criar carteira apenas-visualização</translation>
+ </message>
+ <message>
<source>Error: Keypool ran out, please call keypoolrefill first</source>
<translation type="unfinished">Keypool exaurida, por gentileza execute keypoolrefill primeiro</translation>
</message>
<message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">Erro: Nem todos os txs apenas-visualização foram excluídos</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Erro: Essa carteira já utiliza o SQLite</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">Erro: Esta carteira já contém um descritor</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">Erro: impossível ler todos os registros no banco de dados</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Erro: Impossível efetuar backup da carteira</translation>
+ </message>
+ <message>
+ <source>Error: Unable to parse version %u as a uint32_t</source>
+ <translation type="unfinished">Erro: Impossível analisar versão %u como uint32_t</translation>
+ </message>
+ <message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Erro: Impossível ler todos os registros no banco de dados</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">Erro: Impossível remover dados somente-visualização do Livro de Endereços </translation>
+ </message>
+ <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">Falha ao escutar em qualquer porta. Use -listen=0 se você quiser isso.</translation>
</message>
@@ -610,6 +774,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">O teste de integridade de inicialização falhou. O %s está sendo desligado.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Entrada não encontrada ou já gasta</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">Saldo insuficiente</translation>
</message>
@@ -646,6 +814,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Máscara de rede especificada em -whitelist: '%s' é inválida</translation>
</message>
<message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">A espera por conexões de entrada falharam (a espera retornou o erro %s)</translation>
+ </message>
+ <message>
<source>Loading P2P addresses…</source>
<translation type="unfinished">Carregando endereços P2P...</translation>
</message>
@@ -662,12 +834,20 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Carregando carteira...</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Faltando quantia</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">Não há dados suficientes para estimar o tamanho da transação</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Necessário informar uma porta com -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Nenhum servidor proxy especificado. Use -proxy=&lt;ip&gt; ou proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Nenhum endereço disponível</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -678,10 +858,6 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">O modo prune não pode ser configurado com um valor negativo.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">O modo prune é incompatível com -txindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">O modo prune é incompatível com -txindex.</translation>
</message>
@@ -778,6 +954,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">As quantidades nas transações não podem ser negativas.</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Endereço de troco da transação fora da faixa</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">A transação demorou muito na memória</translation>
</message>
@@ -786,10 +966,18 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">A transação deve ter ao menos um destinatário</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Transação necessita de um endereço de troco, mas não conseguimos gera-lo. </translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Transação muito grande</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Impossível alocar memória para a opção "-maxsigcachesize: '%s' MiB</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished">Erro ao vincular em %s neste computador (bind retornou erro %s)</translation>
</message>
@@ -802,6 +990,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Não foi possível criar arquivo de PID '%s': %s</translation>
</message>
<message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">Impossível localizar e entrada externa UTXO</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation type="unfinished">Não foi possível gerar as chaves iniciais</translation>
</message>
@@ -810,10 +1002,18 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Não foi possível gerar chaves</translation>
</message>
<message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">Impossível analisar -maxuploadtarget: '%s'</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">Não foi possível iniciar o servidor HTTP. Veja o log de depuração para detaihes.</translation>
</message>
<message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">Impossível desconectar carteira antes de migrá-la</translation>
+ </message>
+ <message>
<source>Unknown -blockfilterindex value %s.</source>
<translation type="unfinished">Valor do parâmetro -blockfilterindex desconhecido %s.</translation>
</message>
@@ -830,12 +1030,12 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Rede desconhecida especificada em -onlynet: '%s'</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">Categoria de log desconhecida %s=%s.</translation>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">Nível de log global inválido "-loglevel=%s". Valores válidos: %s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Atualizando banco de dados UTXO</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Categoria de log desconhecida %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -1056,8 +1256,8 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n bloco processado do histórico de transações.</numerusform>
+ <numerusform>%n blocos processados do histórico de transações.</numerusform>
</translation>
</message>
<message>
@@ -1094,7 +1294,7 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
</message>
<message>
<source>Load Partially Signed Bitcoin Transaction</source>
- <translation type="unfinished">Carregar Transação de Bitcoin Parcialmente Assinada</translation>
+ <translation type="unfinished">Carregar</translation>
</message>
<message>
<source>Load PSBT from &amp;clipboard…</source>
@@ -1137,6 +1337,16 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Fechar carteira</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Restaurar Carteira...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Restaurar uma carteira a partir de um arquivo de backup</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Fechar todas as carteiras</translation>
</message>
@@ -1161,6 +1371,21 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Nenhuma carteira disponível</translation>
</message>
<message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Carregar Backup da Carteira</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Restaurar Carteira</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Nome da Carteira</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Janelas</translation>
</message>
@@ -1178,18 +1403,18 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
</message>
<message>
<source>&amp;Hide</source>
- <translation type="unfinished">&amp;Esconder</translation>
+ <translation type="unfinished">E&amp;sconder</translation>
</message>
<message>
<source>S&amp;how</source>
- <translation type="unfinished">S&amp;como</translation>
+ <translation type="unfinished">Mo&amp;strar</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>%n conexão ativa na rede Bitcoin.</numerusform>
+ <numerusform>%nconexões ativas na rede Bitcoin.</numerusform>
</translation>
</message>
<message>
@@ -1200,7 +1425,7 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<message>
<source>Show Peers tab</source>
<extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
- <translation type="unfinished">Mostrar abas De pares.</translation>
+ <translation type="unfinished">Mostra aba de Pares</translation>
</message>
<message>
<source>Disable network activity</source>
@@ -1213,6 +1438,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Ativar atividade de conexões</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Pré-Sincronizando cabeçalhos (%1%)...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Erro: %1</translation>
</message>
@@ -1447,7 +1676,11 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<source>Create wallet warning</source>
<translation type="unfinished">Criar carteira alerta</translation>
</message>
- </context>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Encontrados muitos assinantes externos</translation>
+ </message>
+</context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1487,6 +1720,34 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Restaurar Carteira</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Restaurando Carteira &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Falha ao restaurar carteira</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Aviso ao restaurar carteira</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Mensagem da carteira restaurada</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1648,17 +1909,26 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
</context>
<context>
<name>Intro</name>
- <message>
- <source>%1 GB of space available</source>
- <translation type="unfinished">%1 GB de espaço disponível</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n GB de espaço disponível</numerusform>
+ <numerusform>%n GB de espaço disponível</numerusform>
+ </translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(de %1 GB necessário)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(de %n GB necessário)</numerusform>
+ <numerusform>(de %n GB necessários)</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB necessário para a blockchain completa)</translation>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n GB necessário para a cadeia completa)</numerusform>
+ <numerusform>(%n GB necessários para a cadeia completa)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1672,8 +1942,8 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>(suficiente para restaurar backup de %n dia atrás)</numerusform>
+ <numerusform>(suficiente para restaurar backups de %n dias atrás)</numerusform>
</translation>
</message>
<message>
@@ -1705,10 +1975,6 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Como essa é a primeira vez que o programa é executado, você pode escolher onde %1 armazenará seus dados.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Quando você clica OK, %1 vai começar a baixar e processar todos os %4 da block chain (%2GB) começando com a mais recente transação em %3 quando %4 inicialmente foi lançado.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Limitar o tamanho da blockchain para</translation>
</message>
@@ -1725,6 +1991,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Esta sincronização inicial é muito exigente e pode expor problemas de hardware com o computador que passaram despercebidos anteriormente. Cada vez que você executar o %1, irá continuar baixando de onde parou.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">Quando clicar em OK, %1 iniciará o download e irá processar a cadeia de blocos completa %4 (%2 GB) iniciando com as mais recentes transações em %3 enquanto %4 é processado. </translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished">Se você escolheu limitar o armazenamento da block chain (prunando), os dados históricos ainda devem ser baixados e processados, mas serão apagados no final para manter o uso de disco baixo.</translation>
</message>
@@ -1817,6 +2087,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Desconhecido. Sincronizando cabeçalhos (%1, %2%)...</translation>
</message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Desconhecido. Pré-Sincronizando Cabeçalhos (%1, %2%)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1869,6 +2143,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Minimizar em vez de fechar o programa quando a janela for fechada. Quando essa opção estiver ativa, o programa só será fechado somente pela opção Sair no menu Arquivo.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Opções configuradas nessa caixa de diálogo serão sobrescritas pela linhas de comando: </translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Abrir o arquivo de configuração %1 apartir do diretório trabalho.</translation>
</message>
@@ -1897,10 +2175,25 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Reverter esta configuração requer baixar de novo a blockchain inteira.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">Tamanho máximo do cache do banco de dados. Um cache maior pode contribuir para uma sincronização mais rápida, após a qual o benefício é menos pronunciado para a maioria dos casos de uso. Reduzir o tamanho do cache reduzirá o uso de memória. A memória do mempool não utilizada é compartilhada para este cache.</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Define o número de threads para script de verificação. Valores negativos correspondem ao número de núcleos que você quer deixar livre para o sistema.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = automático, &lt;0 = número de núcleos deixados livres)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Isso permite que você ou ferramentas de terceiros comunique-se com o node através de linha de comando e comandos JSON-RPC.</translation>
+ </message>
+ <message>
<source>Enable R&amp;PC server</source>
<extracomment>An Options window setting to enable the RPC server.</extracomment>
<translation type="unfinished">Ative servidor R&amp;PC</translation>
@@ -1910,6 +2203,11 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">C&amp;arteira</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Mostra a quantia com a taxa já subtraída.</translation>
+ </message>
+ <message>
<source>Subtract &amp;fee from amount by default</source>
<extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
<translation type="unfinished">Subtrair &amp;taxa da quantia por padrão</translation>
@@ -1936,6 +2234,11 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Ative controles &amp;PSBT</translation>
</message>
<message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Mostrar os controles de PSBT (Transação de Bitcoin Parcialmente Assinada).</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">Abrir automaticamente no roteador as portas do cliente Bitcoin. Isto só funcionará se seu roteador suportar UPnP e esta função estiver habilitada.</translation>
</message>
@@ -2012,6 +2315,14 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Escolha a unidade de subdivisão padrão para exibição na interface ou quando enviando moedas.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">URLs de terceiros (exemplo: explorador de blocos) que aparecem na aba de transações como itens do menu de contexto. %s na URL é substituido pela hash da transação. Múltiplas URLs são separadas pela barra vertical |.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">URLs de transação de &amp;terceiros</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Mostrar ou não opções de controle da moeda.</translation>
</message>
@@ -2028,10 +2339,6 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Fonte no painel de visualização:</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Opções nesta tela foram sobreescritas por comandos ou no arquivo de configuração:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Cancelar</translation>
</message>
@@ -2045,14 +2352,22 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirmar redefinição de opções</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Reinicialização do aplicativo necessária para efetivar alterações.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Configuração atuais serão copiadas em "%1".</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">O programa será encerrado. Deseja continuar?</translation>
</message>
<message>
@@ -2087,6 +2402,13 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Não foi possível ler as configurações "%1", %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2196,6 +2518,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Falhou ao assinar transação: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Não é possível assinar entradas enquanto a carteira está trancada.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">Não foi possível assinar mais nenhuma entrada.</translation>
</message>
@@ -2319,6 +2645,11 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Nós</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Ano</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Direção</translation>
@@ -2502,17 +2833,43 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
</message>
<message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
- <translation type="unfinished">O sistema autônomo delineado usado para a diversificação de seleção de nós.</translation>
+ <translation type="unfinished">O sistema autônomo de mapeamento usado para a diversificação de seleção de nós.</translation>
</message>
<message>
<source>Mapped AS</source>
<translation type="unfinished">Mapeado como</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Endereços são retransmitidos para este nó.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Retransmissão de endereços</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">O número total de endereços recebidos deste peer que foram processados (exclui endereços que foram descartados devido à limitação de taxa).</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">O número total de endereços recebidos deste peer que não foram processados devido à limitação da taxa.</translation>
+ </message>
+ <message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">Endereços Processados</translation>
</message>
<message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Endereços com limite de taxa</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation type="unfinished">Janela do Nó</translation>
</message>
@@ -2541,6 +2898,10 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Serviços</translation>
</message>
<message>
+ <source>Whether the peer requested us to relay transactions.</source>
+ <translation type="unfinished">O nó solicita retransmissão de transações.</translation>
+ </message>
+ <message>
<source>Connection Time</source>
<translation type="unfinished">Tempo de conexão</translation>
</message>
@@ -2638,6 +2999,22 @@ Somente é possível assinar com endereços do tipo 'legado'.</translation>
<translation type="unfinished">Executando comando sem nenhuma carteira</translation>
</message>
<message>
+ <source>Ctrl+I</source>
+ <translation type="unfinished">Control+I</translation>
+ </message>
+ <message>
+ <source>Ctrl+T</source>
+ <translation type="unfinished">Control+T</translation>
+ </message>
+ <message>
+ <source>Ctrl+N</source>
+ <translation type="unfinished">Control+N</translation>
+ </message>
+ <message>
+ <source>Ctrl+P</source>
+ <translation type="unfinished">Control+P</translation>
+ </message>
+ <message>
<source>Executing command using "%1" wallet</source>
<translation type="unfinished">Executando comando usando a carteira "%1"</translation>
</message>
@@ -3041,7 +3418,7 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
</message>
<message>
<source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation type="unfinished">Cria uma Transação de Bitcoin Parcialmente Assinada (PSBT) para usar com ex: uma carteira %1 offline, ou uma PSBT-compatível hardware wallet.</translation>
+ <translation type="unfinished">Cria uma Transação de Bitcoin Parcialmente Assinada (PSBT) para usar com, por exemplo, uma carteira %1 offline ou uma carteira física compatível com PSBTs.</translation>
</message>
<message>
<source> from wallet '%1'</source>
@@ -3082,7 +3459,7 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
<message>
<source>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>
<extracomment>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.</extracomment>
- <translation type="unfinished">Por favor, reveja sua proposta de transação. Será produzido uma Transação de Bitcoin Parcialmente Assinada (PSBT) que você pode copiar e assinar com ex: uma carteira %1 offline, ou uma PSBT-compatível hardware wallet.</translation>
+ <translation type="unfinished">Por favor, revise a transação. Será produzido uma Transação de Bitcoin Parcialmente Assinada (PSBT) que você pode copiar e assinar com, por exemplo, uma carteira %1 offline, ou uma carteira física compatível com PSBTs.</translation>
</message>
<message>
<source>Do you want to create this transaction?</source>
@@ -3090,6 +3467,11 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
<translation type="unfinished">Deseja criar esta transação?</translation>
</message>
<message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Por favor, revise a transação. Você pode assinar e enviar a transação ou criar uma Transação de Bitcoin Parcialmente Assinada (PSBT), que você pode copiar e assinar com, por exemplo, uma carteira %1 offline ou uma carteira física compatível com PSBTs.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Revise a sua transação.</translation>
@@ -3142,15 +3524,11 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Uma taxa maior que %1 é considerada uma taxa absurdamente alta.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Pedido de pagamento expirado.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>Confirmação estimada para iniciar em %n bloco.</numerusform>
+ <numerusform>Confirmação estimada para iniciar em %n blocos.</numerusform>
</translation>
</message>
<message>
@@ -3225,14 +3603,6 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
<translation type="unfinished">Mensagem:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Esta é uma cobrança não autenticada.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Esta é uma cobrança autenticada.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Digite um rótulo para este endereço para adicioná-lo no catálogo</translation>
</message>
@@ -3240,14 +3610,6 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">A mensagem que foi anexada ao bitcoin: URI na qual será gravada na transação para sua referência. Nota: Essa mensagem não será gravada publicamente na rede Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pague Para:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Memorizar:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3418,30 +3780,32 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">conflitado com uma transação com %1 confirmações</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/não confirmado, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">no pool de memória</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/não confirmada, na memória</translation>
</message>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">não está no pool de memóra</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/não confirmada, fora da memória</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abandonado</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/não confirmado</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 confirmações</translation>
</message>
<message>
@@ -3487,8 +3851,8 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
+ <numerusform>pronta em mais %n bloco</numerusform>
+ <numerusform>prontas em mais %n blocos</numerusform>
</translation>
</message>
<message>
@@ -3671,7 +4035,7 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
</message>
<message>
<source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation type="unfinished">Mostrar ou não endereços monitorados na lista de transações.</translation>
+ <translation type="unfinished">Se um endereço monitorado está envolvido nesta transação.</translation>
</message>
<message>
<source>User-defined intent/purpose of the transaction.</source>
@@ -3741,6 +4105,11 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kvB" para
<translation type="unfinished">Alcance...</translation>
</message>
<message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Mostrar em %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Exportar histórico de transações</translation>
</message>
@@ -3832,7 +4201,7 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<source>Unable to decode PSBT</source>
- <translation type="unfinished">Não foi possível decodificar PSDBT</translation>
+ <translation type="unfinished">Não foi possível decodificar PSBT</translation>
</message>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_ro.ts b/src/qt/locale/bitcoin_ro.ts
index 714a317449..6936435913 100644
--- a/src/qt/locale/bitcoin_ro.ts
+++ b/src/qt/locale/bitcoin_ro.ts
@@ -239,6 +239,10 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Fișierul de configurări %1 poate fi corupt sau invalid.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Excepție de fugă</translation>
</message>
@@ -383,10 +387,6 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<translation type="unfinished">Eroare la citirea %s! Toate cheile sînt citite corect, dar datele tranzactiei sau anumite intrări din agenda sînt incorecte sau lipsesc.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Eroare: Ascultarea conexiunilor de intrare nu a reuÅŸit (ascultarea a reurnat eroarea %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Estimarea taxei a esuat. Taxa implicita este dezactivata. Asteptati cateva blocuri, sau activati -fallbackfee.</translation>
</message>
@@ -519,10 +519,6 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<translation type="unfinished">Eroare la citirea bazei de date. Oprire.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Eroare la actualizarea bazei de date chainstate</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Eroare: Spațiul pe disc este redus pentru %s</translation>
</message>
@@ -687,10 +683,6 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<translation type="unfinished">Categoria de logging %s=%s nu este suportata.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Actualizarea bazei de date UTXO</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Comentariul (%s) al Agentului Utilizator contine caractere nesigure.</translation>
</message>
@@ -999,6 +991,11 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<translation type="unfinished">Niciun portofel disponibil</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Numele portofelului</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Fereastră</translation>
</message>
@@ -1424,6 +1421,30 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Cel putin %1GB de date vor fi stocate in acest director, si aceasta valoare va creste in timp.</translation>
@@ -1470,10 +1491,6 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<translation type="unfinished">Deoarece este prima lansare a programului poți alege unde %1 va stoca datele sale.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Cand apasati OK, %1 va incepe descarcarea si procesarea intregului %4 blockchain (%2GB) incepand cu cele mai vechi tranzactii din %3 de la lansarea initiala a %4.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">Revenirea la această setare necesită re-descărcarea întregului blockchain. Este mai rapid să descărcați mai întâi rețeaua complet și să o fragmentați mai târziu. Dezactivează unele funcții avansate.</translation>
</message>
@@ -1747,14 +1764,17 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Confirmă resetarea opţiunilor</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Este necesară repornirea clientului pentru a activa schimbările.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Clientul va fi închis. Doriţi să continuaţi?</translation>
</message>
<message>
@@ -2575,10 +2595,6 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">O taxă mai mare de %1 este considerată o taxă absurd de mare</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Cerere de plată expirata</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2655,14 +2671,6 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<translation type="unfinished">Mesaj:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Aceasta este o cerere de plata neautentificata.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Aceasta este o cerere de plata autentificata.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Introduceţi eticheta pentru ca această adresa să fie introdusă în lista de adrese folosite</translation>
</message>
@@ -2670,11 +2678,7 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">un mesaj a fost ataşat la bitcoin: URI care va fi stocat cu tranzacţia pentru referinţa dvs. Notă: Acest mesaj nu va fi trimis către reţeaua bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Plăteşte către:</translation>
- </message>
- </context>
+</context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -2821,26 +2825,22 @@ Semnarea este posibilă numai cu adrese de tip "legacy".</translation>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">in conflict cu o tranzactie cu %1 confirmari</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/neconfirmat, %1</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">nu e in memory pool</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">abandonat</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/neconfirmat</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 confirmări</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts
index dd9bfec0dd..97e519dcfe 100644
--- a/src/qt/locale/bitcoin_ru.ts
+++ b/src/qt/locale/bitcoin_ru.ts
@@ -6,12 +6,16 @@
<translation type="unfinished">Ðажмите правой кнопкой мыши, чтобы изменить Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ метку</translation>
</message>
<message>
+ <source>Create a new address</source>
+ <translation type="unfinished">Создать новый адреÑ</translation>
+ </message>
+ <message>
<source>&amp;New</source>
<translation type="unfinished">&amp;Ðовый</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation type="unfinished">Скопировать выбранный Ð°Ð´Ñ€ÐµÑ Ð² буфер обмена</translation>
+ <translation type="unfinished">Скопировать выбранные адреÑа в буфер обмена</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -23,7 +27,7 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished">Удалить текущий выбранный Ð°Ð´Ñ€ÐµÑ Ð¸Ð· ÑпиÑка</translation>
+ <translation type="unfinished">Удалить выбранные адреÑа из ÑпиÑка</translation>
</message>
<message>
<source>Enter address or label to search</source>
@@ -35,15 +39,19 @@
</message>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">&amp;ЭкÑпорт</translation>
+ <translation type="unfinished">&amp;ЭкÑпортировать</translation>
</message>
<message>
<source>&amp;Delete</source>
<translation type="unfinished">&amp;Удалить</translation>
</message>
<message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">Выберите адреÑа, Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ на них монет</translation>
+ </message>
+ <message>
<source>Choose the address to receive coins with</source>
- <translation type="unfinished">Выберите Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð½ÐµÑ‚</translation>
+ <translation type="unfinished">Выберите адреÑа Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð½ÐµÑ‚</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -58,10 +66,14 @@
<translation type="unfinished">ÐдреÑа получениÑ</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">Это ваши биткоин-адреÑа Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸ платежей. Ð’Ñегда проверÑйте Ñумму и Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÐµÐ»Ñ Ð¿ÐµÑ€ÐµÐ´ отправкой перевода.</translation>
+ </message>
+ <message>
<source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
Signing is only possible with addresses of the type 'legacy'.</source>
- <translation type="unfinished">Это ваши биткойн-адреÑа Ð´Ð»Ñ Ð¿Ñ€Ð¸ÐµÐ¼Ð° платежей. ИÑпользуйте кнопку 'Создать новый Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ' на вкладке получениÑ, чтобы Ñоздать новые адреÑа.
-ПодпиÑÑŒ возможна только Ñ Ð°Ð´Ñ€ÐµÑами типа 'уÑтаревший'.</translation>
+ <translation type="unfinished">Это ваши биткоин-адреÑа Ð´Ð»Ñ Ð¿Ñ€Ð¸ÐµÐ¼Ð° платежей. ИÑпользуйте кнопку "Создать новый Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ" на вкладке получениÑ, чтобы Ñоздать новые адреÑа.
+ПодпиÑÑŒ возможна только Ñ Ð°Ð´Ñ€ÐµÑами типа "уÑтаревший".</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -91,7 +103,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Exporting Failed</source>
- <translation type="unfinished">Ошибка ÑкÑпорта</translation>
+ <translation type="unfinished">Ошибка при ÑкÑпорте</translation>
</message>
</context>
<context>
@@ -137,7 +149,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation type="unfinished">Ð”Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ Ð²Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð´Ð»Ñ Ñ€Ð°Ð·Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸ вашего кошелька.</translation>
+ <translation type="unfinished">Ð”Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÑ‚ Ð²Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŒÐ½Ð¾Ð¹ фразы Ð´Ð»Ñ Ñ€Ð°Ð·Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸ вашего кошелька.</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -169,11 +181,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
- <translation type="unfinished">Введите Ñтарый и новый пароли Ð´Ð»Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ°</translation>
+ <translation type="unfinished">Введите Ñтарую и новую парольные фразы Ð´Ð»Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ°</translation>
</message>
<message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation type="unfinished">Помните, что шифрование кошелька не может полноÑтью защитить ваши биткойны от кражи вредоноÑными программами, заразившими ваш компьютер.</translation>
+ <translation type="unfinished">Помните, что шифрование кошелька не может полноÑтью защитить ваши биткоины от кражи вредоноÑными программами, заразившими ваш компьютер.</translation>
</message>
<message>
<source>Wallet to be encrypted</source>
@@ -185,11 +197,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation type="unfinished">Ваш кошелёк теперь зашифрован.</translation>
+ <translation type="unfinished">Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ð²Ð°Ñˆ кошелёк зашифрован.</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation type="unfinished">Ð’ÐЖÐО: Ð’Ñе предыдущие резервные копии вашего кошелька, которые вы Ñделали, необходимо заменить недавно Ñгенерированным, зашифрованным файлом кошелька. Из Ñоображений безопаÑноÑти, предыдущие резервные копии незашифрованного файла кошелька Ñтанут беÑполезными как только вы начнёте иÑпользовать новый, зашифрованный кошелёк.</translation>
+ <translation type="unfinished">Ð’ÐЖÐО: Ð’Ñе ранее Ñозданные резервные копии вашего кошелька, необходимо заменить только что Ñгенерированным зашифрованным файлом кошелька. Как только вы начнёте иÑпользовать новый, зашифрованный кошелёк, из Ñоображений безопаÑноÑти, предыдущие резервные копии незашифрованного файла кошелька Ñтанут беÑполезными.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
@@ -224,7 +236,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>BanTableModel</name>
<message>
<source>IP/Netmask</source>
- <translation type="unfinished">IP/маÑка подÑети</translation>
+ <translation type="unfinished">IP/МаÑка подÑети</translation>
</message>
<message>
<source>Banned Until</source>
@@ -234,12 +246,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Файл наÑтроек %1 повреждён или имеет неверный формат.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
- <translation type="unfinished">ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°</translation>
+ <translation type="unfinished">ÐеуправлÑемое иÑключение</translation>
</message>
<message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <translation type="unfinished">Произошла Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°. %1 больше не может безопаÑно продолжить и будет закрыт.</translation>
+ <translation type="unfinished">Произошла критичеÑÐºÐ°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°. %1 больше не может продолжать безопаÑную работу и будет закрыт.
+ </translation>
</message>
<message>
<source>Internal error</source>
@@ -247,12 +264,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <translation type="unfinished">Возникла внутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°. %1 попытаетÑÑ Ð¿Ñ€Ð¾Ð´Ð¾Ð»Ð¶Ð¸Ñ‚ÑŒ работу безопаÑно. Это Ð½ÐµÐ¾Ð¶Ð¸Ð´Ð°Ð½Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°, о которой можно Ñообщить, как опиÑано ниже.</translation>
+ <translation type="unfinished">Произошла внутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°. %1 попытаетÑÑ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñно продолжить работу. Ð’Ñ‹ можете Ñообщить об Ñтой ошибке по инÑтрукции ниже.</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">CброÑить наÑтройки до значений по умолчанию или завершить программу без внеÑÐµÐ½Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Произошла Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°. Проверьте, доÑтупна ли запиÑÑŒ в файл наÑтроек, или повторите запуÑк Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð¾Ð¼ -nosettings.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Ошибка: указанный каталог данных "%1" не ÑущеÑтвует.</translation>
</message>
@@ -266,7 +293,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>%1 didn't yet exit safely…</source>
- <translation type="unfinished">%1 ещё не закрылÑÑ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñно...</translation>
+ <translation type="unfinished">%1 ещё не закрылÑÑ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñно…</translation>
</message>
<message>
<source>unknown</source>
@@ -278,7 +305,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation type="unfinished">Введите биткоин-Ð°Ð´Ñ€ÐµÑ (напр. %1)</translation>
+ <translation type="unfinished">Введите биткоин-Ð°Ð´Ñ€ÐµÑ (например,%1)</translation>
</message>
<message>
<source>Unroutable</source>
@@ -354,41 +381,41 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n Ñекунда</numerusform>
+ <numerusform>%n Ñекунды</numerusform>
+ <numerusform>%n Ñекунд</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n минута</numerusform>
+ <numerusform>%n минуты</numerusform>
+ <numerusform>%n минут</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n чаÑ</numerusform>
+ <numerusform>%n чаÑа</numerusform>
+ <numerusform>%n чаÑов</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n день</numerusform>
+ <numerusform>%n днÑ</numerusform>
+ <numerusform>%n дней</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n неделÑ</numerusform>
+ <numerusform>%n недели</numerusform>
+ <numerusform>%n недель</numerusform>
</translation>
</message>
<message>
@@ -398,9 +425,9 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n год</numerusform>
+ <numerusform>%n года</numerusform>
+ <numerusform>%n лет</numerusform>
</translation>
</message>
<message>
@@ -423,12 +450,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Файл наÑтроек не может быть прочитан</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Файл наÑтроек не может быть запиÑан</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">Разработчики %s</translation>
</message>
<message>
<source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
- <translation type="unfinished">%s иÑпорчен. Попробуйте воÑÑтановить Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ инÑтрумента bitcoin-wallet или воÑÑтановите из резервной копии.</translation>
+ <translation type="unfinished">%s иÑпорчен. Попробуйте воÑÑтановить его Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ инÑтрумента bitcoin-wallet или из резервной копии.</translation>
</message>
<message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
@@ -444,17 +479,21 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>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>
- <translation type="unfinished">Ðевозможно обновить разделённый кошелёк без HD Ñ Ð²ÐµÑ€Ñии %i до верÑии %i, не обновившиÑÑŒ Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ предварительно разделённого пула ключей. ПожалуйÑта, иÑпользуйте верÑию %iили повторите без ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð²ÐµÑ€Ñии.</translation>
+ <translation type="unfinished">Ðевозможно обновить разделённый кошелёк без HD Ñ Ð²ÐµÑ€Ñии %i до верÑии %i, не обновившиÑÑŒ Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ предварительно разделённого пула ключей. ПожалуйÑта, иÑпользуйте верÑию %i или повторите без ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð²ÐµÑ€Ñии.</translation>
</message>
<message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
- <translation type="unfinished">РаÑпроÑтранÑетÑÑ Ð¿Ð¾Ð´ лицензией MIT, Ñм. приложенный файл %s или %s</translation>
+ <translation type="unfinished">РаÑпроÑтранÑетÑÑ Ð¿Ð¾ лицензии MIT. Её текÑÑ‚ находитÑÑ Ð² файле %s и по адреÑу %s</translation>
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
<translation type="unfinished">Ошибка Ñ‡Ñ‚ÐµÐ½Ð¸Ñ %s! Ð’Ñе ключи прочитаны верно, но данные транзакций или запиÑи адреÑной книги могут отÑутÑтвовать или быть неправильными.</translation>
</message>
<message>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Ошибка Ñ‡Ñ‚ÐµÐ½Ð¸Ñ %s! Данные транзакций отÑутÑтвуют или неправильны. Кошелёк ÑканируетÑÑ Ð·Ð°Ð½Ð¾Ð²Ð¾.</translation>
+ </message>
+ <message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
<translation type="unfinished">Ошибка: запиÑÑŒ формата дамп-файла неверна. Обнаружено "%s", ожидалоÑÑŒ "format".</translation>
</message>
@@ -464,11 +503,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
- <translation type="unfinished">Ошибка: верÑÐ¸Ñ Ð´Ð°Ð¼Ð¿-файла не поддерживаетÑÑ. Эта верÑÐ¸Ñ bitcoin-wallet поддерживает только дамп-файлы верÑии 1. Обнаружено дамп-файл верÑии %s</translation>
+ <translation type="unfinished">Ошибка: верÑÐ¸Ñ Ð´Ð°Ð¼Ð¿-файла не поддерживаетÑÑ. Эта верÑÐ¸Ñ Ð±Ð¸Ñ‚ÐºÐ¾Ð¸Ð½-кошелька поддерживает только дамп-файлы верÑии 1. Обнаружен дамп-файл верÑии %s</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Ошибка: Ðе удалоÑÑŒ начать проÑлушивание входÑщих подключений (проÑлушивание вернуло ошибку %s)</translation>
+ <source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
+ <translation type="unfinished">Ошибка: уÑтаревшие кошельки поддерживают только Ñледующие типы адреÑов: "legacy", "p2sh-segwit", и "bech32".</translation>
</message>
<message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
@@ -480,7 +519,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
- <translation type="unfinished">Ðеверное значение Ð´Ð»Ñ -maxtxfee=&lt;amount&gt;: '%s' (должна быть не ниже минимально ретранÑлируемой комиÑÑии %s Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð·Ð°Ð²Ð¸ÑÐ°Ð½Ð¸Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ð¹)</translation>
+ <translation type="unfinished">Ðеверное значение Ð´Ð»Ñ -maxtxfee=&lt;amount&gt;: "%s" (должно быть не ниже минимально ретранÑлируемой комиÑÑии %s Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð·Ð°Ð²Ð¸ÑÐ°Ð½Ð¸Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ð¹)</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Ðеверный или поврежденный peers.dat (%s). ЕÑли вы Ñчитаете что Ñто ошибка, Ñообщите о ней %s. Ð’ качеÑтве временной меры вы можете перемеÑтить, переименовать или удалить файл (%s). Ðовый файл будет Ñоздан при Ñледующем запуÑке программы.</translation>
</message>
<message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
@@ -500,7 +543,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
- <translation type="unfinished">ПожалуйÑта, убедитеÑÑŒ, что на вашем компьютере верно уÑтановлены дата и времÑ. ЕÑли ваши чаÑÑ‹ неверны, %s не будет работать правильно.</translation>
+ <translation type="unfinished">ПожалуйÑта, убедитеÑÑŒ, что на вашем компьютере верно уÑтановлены дата и времÑ. ЕÑли ваши чаÑÑ‹ ÑбилиÑÑŒ, %s будет работать неправильно.</translation>
</message>
<message>
<source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
@@ -511,32 +554,40 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Обрезка блоков выÑтавлена меньше, чем минимум в %d МиБ. ПожалуйÑта, иÑпользуйте большее значение.</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">Режим обрезки неÑовмеÑтим Ñ -reindex-chainstate. ИÑпользуйте вмеÑто Ñтого полный -reindex.</translation>
+ </message>
+ <message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished">Обрезка: поÑледнÑÑ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ° вышла за рамки обрезанных данных. Ðеобходимо Ñделать -reindex (Ñнова Ñкачать вÑÑŽ цепочку блоков, еÑли у Ð²Ð°Ñ ÑƒÐ·ÐµÐ» Ñ Ð¾Ð±Ñ€ÐµÐ·ÐºÐ¾Ð¹)</translation>
</message>
<message>
<source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
- <translation type="unfinished">SQLiteDatabase: ÐеизвеÑÑ‚Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñхемы sqlite кошелька: %d. ПоддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ верÑÐ¸Ñ %d</translation>
+ <translation type="unfinished">SQLiteDatabase: неизвеÑÑ‚Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñхемы SQLite кошелька: %d. ПоддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ верÑÐ¸Ñ %d</translation>
</message>
<message>
<source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
<translation type="unfinished">Ð’ базе данных блоков найден блок из будущего. Это может произойти из-за неверно уÑтановленных даты и времени на вашем компьютере. ПереÑтраивайте базу данных блоков только еÑли вы уверены, что дата и Ð²Ñ€ÐµÐ¼Ñ ÑƒÑтановлены верно.</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">База данных индекÑации блоков Ñодержит уÑтаревший "txindex". Чтобы оÑвободить меÑто на диÑке, выполните полный -reindex, или игнорируйте Ñту ошибку. Это Ñообщение об ошибке больше показано не будет.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
- <translation type="unfinished">Сумма транзакции за вычетом комиÑÑии Ñлишком мала</translation>
+ <translation type="unfinished">Сумма транзакции за вычетом комиÑÑии Ñлишком мала Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">Ð”Ð°Ð½Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° может произойти в том Ñлучае, еÑли Ñтот кошелёк не был правильно закрыт и в поÑледний раз был загружен иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð²ÐµÑ€Ñию Ñ Ð±Ð¾Ð»ÐµÐµ новой верÑией Berkley DB. ЕÑли Ñто так, воÑпользуйтеÑÑŒ той программой, в которой Ñтот кошелёк открывалÑÑ Ð² поÑледний раз.</translation>
+ <translation type="unfinished">Это могло произойти, еÑли кошелёк был некорректно закрыт, а затем загружен Ñборкой Ñ Ð±Ð¾Ð»ÐµÐµ новой верÑией Berkley DB. ЕÑли Ñто так, воÑпользуйтеÑÑŒ Ñборкой, в которой Ñтот кошелёк открывалÑÑ Ð² поÑледний раз</translation>
</message>
<message>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
- <translation type="unfinished">Это теÑÑ‚Ð¾Ð²Ð°Ñ Ñборка - иÑпользуйте на Ñвой Ñтрах и риÑк - не иÑпользуйте Ð´Ð»Ñ Ð´Ð¾Ð±Ñ‹Ñ‡Ð¸ или торговых приложений</translation>
+ <translation type="unfinished">Это теÑÑ‚Ð¾Ð²Ð°Ñ Ñборка. ИÑпользуйте её на Ñвой Ñтрах и риÑк. Ðе иÑпользуйте её Ð´Ð»Ñ Ð´Ð¾Ð±Ñ‹Ñ‡Ð¸ или в торговых приложениÑÑ…</translation>
</message>
<message>
<source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
- <translation type="unfinished">Это макÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ, которую вы заплатите (в добавок к обычной плате), чтобы отдать приоритет избежанию чаÑтичной траты перед обычным управлением монетами.</translation>
+ <translation type="unfinished">Это макÑÐ¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð¼Ð¸ÑÑÐ¸Ñ Ð·Ð° транзакцию, которую вы заплатите (в добавок к обычной комиÑÑии), чтобы отдать приоритет избежанию чаÑтичной траты перед обычным управлением монетами.</translation>
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
@@ -552,15 +603,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation type="unfinished">Ðевозможно воÑпроизвеÑти блоки. Вам необходимо переÑтроить базу данных, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ -reindex-chaintate.</translation>
+ <translation type="unfinished">Ðевозможно воÑпроизвеÑти блоки. Вам необходимо переÑтроить базу данных, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ -reindex-chainstate.</translation>
</message>
<message>
<source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
<translation type="unfinished">Указан неизвеÑтный формат файла кошелька "%s". Укажите "bdb" либо "sqlite".</translation>
</message>
<message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Обнаружен неподдерживаемый формат базы данных ÑоÑтоÑÐ½Ð¸Ñ Ñ†ÐµÐ¿Ð¾Ñ‡ÐºÐ¸ блоков. ПожалуйÑта, перезапуÑтите программу Ñ ÐºÐ»ÑŽÑ‡Ð¾Ð¼ -reindex-chainstate. Это переÑтроит базу данных ÑоÑтоÑÐ½Ð¸Ñ Ñ†ÐµÐ¿Ð¾Ñ‡ÐºÐ¸ блоков.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Кошелёк уÑпешно Ñоздан. Старый формат кошелька признан уÑтаревшим. Поддержка ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ° в Ñтом формате и его открытие в будущем будут удалены.</translation>
+ </message>
+ <message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
- <translation type="unfinished">Внимание: формат кошелька дамп-файла "%s" не ÑоответÑтвует указанному в командной Ñтроке формату "%s".</translation>
+ <translation type="unfinished">Внимание: формат дамп-файла кошелька "%s" не ÑоответÑтвует указанному в командной Ñтроке формату "%s".</translation>
</message>
<message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
@@ -568,7 +627,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
- <translation type="unfinished">Внимание: мы не полноÑтью ÑоглаÑны Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ узлами! Вам или другим учаÑтникам, возможно, Ñледует обновить клиент.</translation>
+ <translation type="unfinished">Внимание: мы не полноÑтью ÑоглаÑны Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ узлами! Вам или другим учаÑтникам, возможно, Ñледует обновитьÑÑ.</translation>
</message>
<message>
<source>Witness data for blocks after height %d requires validation. Please restart with -reindex.</source>
@@ -584,27 +643,127 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>-maxmempool must be at least %d MB</source>
- <translation type="unfinished">-maxmempool должен быть как минимум %d МБ</translation>
+ <translation type="unfinished">-maxmempool должен быть минимум %d МБ</translation>
</message>
<message>
<source>A fatal internal error occurred, see debug.log for details</source>
- <translation type="unfinished">Ошибка: произошла критичеÑÐºÐ°Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°, Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´ÐµÑ‚Ð°Ð»ÐµÐ¹ Ñм. debug.log</translation>
+ <translation type="unfinished">Произошла критичеÑÐºÐ°Ñ Ð²Ð½ÑƒÑ‚Ñ€ÐµÐ½Ð½ÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ°, подробноÑти в файле debug.log</translation>
</message>
<message>
<source>Cannot resolve -%s address: '%s'</source>
- <translation type="unfinished">Ðе удаетÑÑ Ñ€Ð°Ð·Ñ€ÐµÑˆÐ¸Ñ‚ÑŒ -%s адреÑ: '%s'</translation>
+ <translation type="unfinished">Ðе удаетÑÑ Ñ€Ð°Ð·Ñ€ÐµÑˆÐ¸Ñ‚ÑŒ -%s адреÑ: "%s"</translation>
+ </message>
+ <message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">ÐÐµÐ»ÑŒÐ·Ñ ÑƒÑтановить -forcednsseed в true, еÑли -dnsseed уÑтановлен в false.</translation>
</message>
<message>
<source>Cannot set -peerblockfilters without -blockfilterindex.</source>
- <translation type="unfinished">ÐÐµÐ»ÑŒÐ·Ñ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ -peerblockfilters без -blockfilterindex.</translation>
+ <translation type="unfinished">ÐÐµÐ»ÑŒÐ·Ñ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ -peerblockfilters без ÑƒÐºÐ°Ð·Ð°Ð½Ð¸Ñ -blockfilterindex.</translation>
</message>
<message>
<source>Cannot write to data directory '%s'; check permissions.</source>
- <translation type="unfinished">Ðе удаетÑÑ Ð²Ñ‹Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÑŒ запиÑÑŒ в каталог данных '%s'; проверьте разрешениÑ.</translation>
+ <translation type="unfinished">Ðе удаетÑÑ Ð²Ñ‹Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÑŒ запиÑÑŒ в каталог данных "%s"; проверьте разрешениÑ.</translation>
+ </message>
+ <message>
+ <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">Обновление -txindex, запущенное при предыдущей верÑии не может быть завершено. ПерезапуÑтите Ñ Ð¿Ñ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰ÐµÐ¹ верÑией или запуÑтите веÑÑŒ процеÑÑ Ð·Ð°Ð½Ð¾Ð²Ð¾ Ñ ÐºÐ»ÑŽÑ‡Ð¾Ð¼ -reindex.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s попыталÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚ÑŒ на проÑлушивание порт %u. Этот порт ÑчитаетÑÑ "плохим". ВероÑтноÑÑ‚ÑŒ, что узлы Bitcoin Core к нему подключатÑÑ, крайне мала. ПодробноÑти и полный ÑпиÑок плохих портов в документации: doc/p2p-bad-ports.md. </translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">ÐžÐ¿Ñ†Ð¸Ñ -reindex-chainstate не ÑовмеÑтима Ñ -blockfilterindex. ПожалуйÑта, выключите на Ð²Ñ€ÐµÐ¼Ñ blockfilterindex, пока иÑпользуетÑÑ -reindex-chainstate, либо замените -reindex-chainstate на -reindex Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ переÑтройки вÑех индекÑов.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">ÐžÐ¿Ñ†Ð¸Ñ -reindex-chainstate не ÑовмеÑтима Ñ -coinstatsindex. ПожалуйÑта, выключите на Ð²Ñ€ÐµÐ¼Ñ coinstatsindex, пока иÑпользуетÑÑ -reindex-chainstate, либо замените -reindex-chainstate на -reindex Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ переÑтройки вÑех индекÑов.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">ÐžÐ¿Ñ†Ð¸Ñ -reindex-chainstate не ÑовмеÑтима Ñ -txindex. ПожалуйÑта, выключите на Ð²Ñ€ÐµÐ¼Ñ txindex, пока иÑпользуетÑÑ -reindex-chainstate, либо замените -reindex-chainstate на -reindex Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ переÑтройки вÑех индекÑов.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Предположительно дейÑтвительный: поÑледнÑÑ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ° была Ñ Ð±Ð¾Ð»ÐµÐµ новым блоком данных, чем имеетÑÑ Ñƒ наÑ. Подождите, пока фоновый процеÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ цепочки блоков загрузит новые данные.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Ðе удаётÑÑ Ð¿Ñ€ÐµÐ´Ð¾Ñтавить определённые ÑоединениÑ, чтобы при Ñтом addrman нашёл в них иÑходÑщие ÑоединениÑ.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Ошибка загрузки %s: не удалоÑÑŒ загрузить кошелёк Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ¹ подпиÑью, так как Ñта верÑÐ¸Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹ Ñобрана без поддержки внешней подпиÑи</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Ошибка: адреÑÐ½Ð°Ñ ÐºÐ½Ð¸Ð³Ð° в кошельке не принадлежит к мигрируемым кошелькам</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">Ошибка: при миграции были Ñозданы дублирующиеÑÑ Ð´ÐµÑкрипторы. Возможно, ваш кошелёк повреждён.</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Ошибка: Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ %s не принадлежит к мигрируемым кошелькам</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">Ошибка: не удалоÑÑŒ Ñоздать деÑкрипторы Ð´Ð»Ñ Ñтого кошелька Ñтарого формата. Ð”Ð»Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° убедитеÑÑŒ, что кошелёк разблокирован</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Ðе удалоÑÑŒ переименовать файл peers.dat. ПожалуйÑта, перемеÑтите или удалите его и попробуйте Ñнова.</translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">ÐеÑовмеÑтимые ключи: был Ñвно указан -dnsseed=1, но -onlynet не разрешены ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· IPv4/IPv6</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">ИÑходÑщие ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ñ‹ только через Ñеть Tor (-onlynet=onion), однако прокÑи Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Ñети Tor Ñвно запрещен: -onion=0</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">ИÑходÑщие ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ñ‹ только через Ñеть Tor (-onlynet=onion), однако прокÑи Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Ñети Tor не указан: не заданы ни -proxy, ни -onion, ни -listenonion</translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">При загрузке кошелька %s найден нераÑпознаваемый деÑкриптор
+
+Кошелёк мог быть Ñоздан на более новой верÑии программы.
+ПожалуйÑта, попробуйте обновить программу до поÑледней верÑии.
+</translation>
+ </message>
+ <message>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished">Ðеподдерживаемый уровень подробноÑти журнала Ð´Ð»Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ð¸ -loglevel=%s. ОжидалоÑÑŒ -loglevel=&lt;category&gt;:&lt;loglevel&gt;. ДоÑтупные категории: %s. ДоÑтупные уровни подробноÑти журнала: %s.</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+Ðе удалоÑÑŒ очиÑтить Ñледы поÑле неуÑпешной миграции</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Ðе удалоÑÑŒ воÑÑтановить кошелёк из резервной копии.</translation>
</message>
<message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
- <translation type="unfinished">ÐаÑтройка конфигурации %s применÑетÑÑ Ð² Ñети %s только еÑли находитÑÑ Ð² разделе [%s].</translation>
+ <translation type="unfinished">ÐаÑтройка конфигурации %s применÑетÑÑ Ð´Ð»Ñ Ñети %s только еÑли находитÑÑ Ð² разделе [%s].</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation type="unfinished">ÐвторÑкое право (C) %i-%i</translation>
</message>
<message>
<source>Corrupted block database detected</source>
@@ -616,11 +775,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Could not parse asmap file %s</source>
- <translation type="unfinished">Ðе могу разобрать файл asmap %s</translation>
+ <translation type="unfinished">Ðе удалоÑÑŒ разобрать файл asmap %s</translation>
</message>
<message>
<source>Disk space is too low!</source>
- <translation type="unfinished">Мало меÑта на диÑке!</translation>
+ <translation type="unfinished">МеÑто на диÑке заканчиваетÑÑ!</translation>
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
@@ -632,23 +791,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Dump file %s does not exist.</source>
- <translation type="unfinished">Дамп файл %s не ÑущеÑтвует.</translation>
+ <translation type="unfinished">Дамп-файл %s не ÑущеÑтвует.</translation>
</message>
<message>
<source>Error creating %s</source>
- <translation type="unfinished">Ошибка загрузки %s</translation>
+ <translation type="unfinished">Ошибка при Ñоздании %s</translation>
</message>
<message>
<source>Error initializing block database</source>
- <translation type="unfinished">Ошибка инициализации базы данных блоков</translation>
+ <translation type="unfinished">Ошибка при инициализации базы данных блоков</translation>
</message>
<message>
<source>Error initializing wallet database environment %s!</source>
- <translation type="unfinished">Ошибка инициализации Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных кошелька %s!</translation>
+ <translation type="unfinished">Ошибка при инициализации Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных кошелька %s!</translation>
</message>
<message>
<source>Error loading %s</source>
- <translation type="unfinished">Ошибка загрузки %s</translation>
+ <translation type="unfinished">Ошибка при загрузке %s</translation>
</message>
<message>
<source>Error loading %s: Private keys can only be disabled during creation</source>
@@ -679,8 +838,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ошибка Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ñледующей запиÑи из базы данных кошелька</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Ошибка Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных chainstate</translation>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">Ошибка: не удалоÑÑŒ добавить транзакцию Ð´Ð»Ñ Ð½Ð°Ð±Ð»ÑŽÐ´ÐµÐ½Ð¸Ñ Ð² кошелек Ð´Ð»Ñ Ð½Ð°Ð±Ð»ÑŽÐ´ÐµÐ½Ð¸Ñ</translation>
+ </message>
+ <message>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">Ошибка: транзакции только Ð´Ð»Ñ Ð½Ð°Ð±Ð»ÑŽÐ´ÐµÐ½Ð¸Ñ Ð½Ðµ удалÑÑŽÑ‚ÑÑ</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
@@ -692,11 +855,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
- <translation type="unfinished">Ошибка: ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма дамп-файла не Ñовпадает. ВычиÑлено %s, ожидалоÑÑŒ %s.</translation>
+ <translation type="unfinished">Ошибка: контрольные Ñуммы дамп-файла не Ñовпадают. ВычиÑлено %s, ожидалоÑÑŒ %s.</translation>
+ </message>
+ <message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">Ошибка: не удалоÑÑŒ Ñоздать кошелёк только на проÑмотр</translation>
</message>
<message>
<source>Error: Got key that was not hex: %s</source>
- <translation type="unfinished">Ошибка: получен ключ, оказавшийÑÑ Ð½Ðµ шеÑтнадцатеричным: %s</translation>
+ <translation type="unfinished">Ошибка: получен ключ, не ÑвлÑющийÑÑ ÑˆÐµÑтнадцатеричным: %s</translation>
</message>
<message>
<source>Error: Got value that was not hex: %s</source>
@@ -704,23 +871,55 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Error: Keypool ran out, please call keypoolrefill first</source>
- <translation type="unfinished">Ошибка: пул ключей опуÑтел, пожалуйÑта Ñначала выполните keypoolrefill</translation>
+ <translation type="unfinished">Ошибка: пул ключей опуÑтел. ПожалуйÑта, выполните keypoolrefill</translation>
</message>
<message>
<source>Error: Missing checksum</source>
<translation type="unfinished">Ошибка: отÑутÑтвует ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð°Ñ Ñумма</translation>
</message>
<message>
+ <source>Error: No %s addresses available.</source>
+ <translation type="unfinished">Ошибка: нет %s доÑтупных адреÑов.</translation>
+ </message>
+ <message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">Ошибка: не вÑе наблюдаемые транзакции могут быть удалены</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Ошибка: Ñтот кошелёк уже иÑпользует SQLite</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">Ошибка: Ñтот кошелёк уже ÑвлÑетÑÑ Ð´ÐµÑкрипторным</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">Ошибка: не удалоÑÑŒ начать читать вÑе запиÑи из базе данных</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Ошибка: не удалоÑÑŒ Ñоздать резервную копию кошелька</translation>
+ </message>
+ <message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">Ошибка: невозможно разобрать верÑию %u как uint32_t</translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Ошибка: не удалоÑÑŒ прочитать вÑе запиÑи из базе данных</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">Ошибка: не удалоÑÑŒ удалить данные из адреÑной книги только Ð´Ð»Ñ Ð½Ð°Ð±Ð»ÑŽÐ´ÐµÐ½Ð¸Ñ</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
<translation type="unfinished">Ошибка: невозможно произвеÑти запиÑÑŒ в новый кошелек</translation>
</message>
<message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
- <translation type="unfinished">Ðе удалоÑÑŒ начать проÑлушивание на порту. ИÑпользуйте -listen=0, еÑли Ð²Ð°Ñ Ñто уÑтраивает.</translation>
+ <translation type="unfinished">Ðе удалоÑÑŒ открыть никакой порт на проÑлушивание. ИÑпользуйте -listen=0, еÑли Ð²Ð°Ñ Ñто уÑтроит.</translation>
</message>
<message>
<source>Failed to rescan the wallet during initialization</source>
@@ -740,7 +939,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Importing…</source>
- <translation type="unfinished">Импорт...</translation>
+ <translation type="unfinished">Импорт…</translation>
</message>
<message>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
@@ -751,68 +950,84 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ÐÐ°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ° иÑправноÑти не удалаÑÑŒ. %s завершает работу.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Вход Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð·Ð°ÐºÑ†Ð¸Ð¸ не найден или уже иÑпользован</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">ÐедоÑтаточно ÑредÑтв</translation>
</message>
<message>
<source>Invalid -i2psam address or hostname: '%s'</source>
- <translation type="unfinished">Ðеверный Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ Ð¸Ð¼Ñ Ñ…Ð¾Ñта в -i2psam: '%s'</translation>
+ <translation type="unfinished">Ðеверный Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ Ð¸Ð¼Ñ Ñ…Ð¾Ñта в -i2psam: "%s"</translation>
</message>
<message>
<source>Invalid -onion address or hostname: '%s'</source>
- <translation type="unfinished">Ðеверный -onion Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ Ð¸Ð¼Ñ Ñ…Ð¾Ñта: '%s'</translation>
+ <translation type="unfinished">Ðеверный -onion Ð°Ð´Ñ€ÐµÑ Ð¸Ð»Ð¸ Ð¸Ð¼Ñ Ñ…Ð¾Ñта: "%s"</translation>
</message>
<message>
<source>Invalid -proxy address or hostname: '%s'</source>
- <translation type="unfinished">Ðеверный Ð°Ð´Ñ€ÐµÑ -proxy или Ð¸Ð¼Ñ Ñ…Ð¾Ñта: '%s'</translation>
+ <translation type="unfinished">Ðеверный Ð°Ð´Ñ€ÐµÑ -proxy или Ð¸Ð¼Ñ Ñ…Ð¾Ñта: "%s"</translation>
</message>
<message>
<source>Invalid P2P permission: '%s'</source>
- <translation type="unfinished">Ðеверные разрешение Ð´Ð»Ñ P2P: '%s'</translation>
+ <translation type="unfinished">Ðеверные Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð´Ð»Ñ P2P: "%s"</translation>
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation type="unfinished">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñумма Ð´Ð»Ñ -%s=&lt;amount&gt;: '%s'</translation>
+ <translation type="unfinished">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñумма Ð´Ð»Ñ -%s=&lt;amount&gt;: "%s"</translation>
</message>
<message>
<source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation type="unfinished">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñумма Ð´Ð»Ñ -discardfee=&lt;amount&gt;: '%s'</translation>
+ <translation type="unfinished">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñумма Ð´Ð»Ñ -discardfee=&lt;amount&gt;: "%s"</translation>
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation type="unfinished">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñумма Ð´Ð»Ñ -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ <translation type="unfinished">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñумма Ð´Ð»Ñ -fallbackfee=&lt;amount&gt;: "%s"</translation>
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation type="unfinished">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñумма Ð´Ð»Ñ -paytxfee=&lt;amount&gt;: '%s' (должно быть как минимум %s)</translation>
+ <translation type="unfinished">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñумма Ð´Ð»Ñ -paytxfee=&lt;amount&gt;: "%s" (должно быть как минимум %s)</translation>
</message>
<message>
<source>Invalid netmask specified in -whitelist: '%s'</source>
- <translation type="unfinished">Указана Ð½ÐµÐ²ÐµÑ€Ð½Ð°Ñ ÑÐµÑ‚ÐµÐ²Ð°Ñ Ð¼Ð°Ñка в -whitelist: '%s'</translation>
+ <translation type="unfinished">Указана Ð½ÐµÐ²ÐµÑ€Ð½Ð°Ñ ÑÐµÑ‚ÐµÐ²Ð°Ñ Ð¼Ð°Ñка в -whitelist: "%s"</translation>
+ </message>
+ <message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">Ошибка при проÑлушивании входÑщих подключений (%s)</translation>
</message>
<message>
<source>Loading P2P addresses…</source>
- <translation type="unfinished">Загрузка P2P адреÑов...</translation>
+ <translation type="unfinished">Загрузка P2P адреÑов…</translation>
</message>
<message>
<source>Loading banlist…</source>
- <translation type="unfinished">Загрузка черного ÑпиÑка...</translation>
+ <translation type="unfinished">Загрузка черного ÑпиÑка…</translation>
</message>
<message>
<source>Loading block index…</source>
- <translation type="unfinished">Загрузка индекÑа блоков...</translation>
+ <translation type="unfinished">Загрузка индекÑа блоков…</translation>
</message>
<message>
<source>Loading wallet…</source>
- <translation type="unfinished">Загрузка кошелька...</translation>
+ <translation type="unfinished">Загрузка кошелька…</translation>
+ </message>
+ <message>
+ <source>Missing amount</source>
+ <translation type="unfinished">ОтÑутÑтвует Ñумма</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">ÐедоÑтаточно данных Ð´Ð»Ñ Ð¾Ñ†ÐµÐ½ÐºÐ¸ размера транзакции</translation>
</message>
<message>
<source>Need to specify a port with -whitebind: '%s'</source>
- <translation type="unfinished">Ðеобходимо указать порт Ñ -whitebind: '%s'</translation>
+ <translation type="unfinished">Ðеобходимо указать порт Ñ -whitebind: "%s"</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Ðе указан прокÑи-Ñервер. ИÑпользуйте -proxy=&lt;ip&gt; или -proxy=&lt;ip:port&gt;</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Ðет доÑтупных адреÑов</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -823,48 +1038,44 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Обрезка блоков не может иÑпользовать отрицательное значение.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Режим ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¾Ð² неÑовмеÑтим Ñ -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Режим обрезки неÑовмеÑтим Ñ -txindex.</translation>
</message>
<message>
<source>Pruning blockstore…</source>
- <translation type="unfinished">Сокращение объема хранилища блоков...</translation>
+ <translation type="unfinished">Сокращение хранилища блоков…</translation>
</message>
<message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
- <translation type="unfinished">Уменьшите -maxconnections Ñ %d до %d из-за ограничений ÑиÑтемы.</translation>
+ <translation type="unfinished">Уменьшение -maxconnections Ñ %d до %d из-за ограничений ÑиÑтемы.</translation>
</message>
<message>
<source>Replaying blocks…</source>
- <translation type="unfinished">ПереÑборка блоков...</translation>
+ <translation type="unfinished">ПереÑборка блоков…</translation>
</message>
<message>
<source>Rescanning…</source>
- <translation type="unfinished">ПереÑканирование...</translation>
+ <translation type="unfinished">Повторное Ñканирование…</translation>
</message>
<message>
<source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
- <translation type="unfinished">SQLiteDatabase: Ðе удалоÑÑŒ выполнить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ базы данных: %s</translation>
+ <translation type="unfinished">SQLiteDatabase: не удалоÑÑŒ выполнить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ базы данных: %s</translation>
</message>
<message>
<source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
- <translation type="unfinished">SQLiteDatabase: Ðе удалоÑÑŒ подготовить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ базы данных: %s</translation>
+ <translation type="unfinished">SQLiteDatabase: не удалоÑÑŒ подготовить Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ базы данных: %s</translation>
</message>
<message>
<source>SQLiteDatabase: Failed to read database verification error: %s</source>
- <translation type="unfinished">SQLiteDatabase: Ошибка при проверке базы данных: %s</translation>
+ <translation type="unfinished">SQLiteDatabase: ошибка при проверке базы данных: %s</translation>
</message>
<message>
<source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
- <translation type="unfinished">SQLiteDatabase: Ðеожиданный id приложениÑ. ОжидалоÑÑŒ %u, но получено %u</translation>
+ <translation type="unfinished">SQLiteDatabase: неожиданный id приложениÑ. ОжидалоÑÑŒ %u, но получено %u</translation>
</message>
<message>
<source>Section [%s] is not recognized.</source>
- <translation type="unfinished">Раздел [%s] не раÑпознан.</translation>
+ <translation type="unfinished">Ð¡ÐµÐºÑ†Ð¸Ñ [%s] не раÑпознана.</translation>
</message>
<message>
<source>Signing transaction failed</source>
@@ -880,19 +1091,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Specified -walletdir "%s" is not a directory</source>
- <translation type="unfinished">Указанный -walletdir "%s" не ÑвлÑетÑÑ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸ÐµÐ¹</translation>
+ <translation type="unfinished">Указанный -walletdir "%s" не ÑвлÑетÑÑ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¾Ð¼</translation>
</message>
<message>
<source>Specified blocks directory "%s" does not exist.</source>
- <translation type="unfinished">Ð£ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð´Ð»Ñ Ð±Ð»Ð¾ÐºÐ¾Ð² "%s" не ÑущеÑтвует.</translation>
+ <translation type="unfinished">Указанный каталог блоков "%s" не ÑущеÑтвует.</translation>
</message>
<message>
<source>Starting network threads…</source>
- <translation type="unfinished">ЗапуÑк Ñетевых потоков...</translation>
+ <translation type="unfinished">ЗапуÑк Ñетевых потоков…</translation>
</message>
<message>
<source>The source code is available from %s.</source>
- <translation type="unfinished">ИÑходный код доÑтупен в %s.</translation>
+ <translation type="unfinished">ИÑходный код доÑтупен по адреÑу %s.</translation>
</message>
<message>
<source>The specified config file %s does not exist</source>
@@ -904,11 +1115,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation type="unfinished">Кошелёк будет ÑтаратьÑÑ Ð½Ðµ платить меньше, чем Ð¼Ð¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð¼Ð¸ÑÑии ретранÑлÑции.</translation>
+ <translation type="unfinished">Кошелёк будет ÑтаратьÑÑ Ð¿Ð»Ð°Ñ‚Ð¸Ñ‚ÑŒ не меньше минимальной комиÑÑии Ð´Ð»Ñ Ñ€ÐµÑ‚Ñ€Ð°Ð½ÑлÑции.</translation>
</message>
<message>
<source>This is experimental software.</source>
- <translation type="unfinished">Это ÑкÑÐ¿ÐµÑ€Ð¸Ð¼ÐµÐ½Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð°.</translation>
+ <translation type="unfinished">Это ÑкÑпериментальное программное обеÑпечение.</translation>
</message>
<message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
@@ -927,28 +1138,44 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Сумма транзакции не должна быть отрицательной</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Ð˜Ð½Ð´ÐµÐºÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÐµÐ»Ñ Ð°Ð´Ñ€ÐµÑа Ñдачи вне диапазона</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
- <translation type="unfinished">Ð’ транзакции Ñлишком Ð´Ð»Ð¸Ð½Ð½Ð°Ñ Ñ†ÐµÐ¿Ð¾Ñ‡ÐºÐ° пула памÑти</translation>
+ <translation type="unfinished">У транзакции Ñлишком Ð´Ð»Ð¸Ð½Ð½Ð°Ñ Ñ†ÐµÐ¿Ð¾Ñ‡ÐºÐ° в пуле в памÑти</translation>
</message>
<message>
<source>Transaction must have at least one recipient</source>
<translation type="unfinished">Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° иметь Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одного получателÑ</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Ð”Ð»Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ð¸ требуетÑÑ Ð°Ð´Ñ€ÐµÑ Ñдачи, но Ñгенерировать его не удалоÑÑŒ.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ Ñлишком большаÑ</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Ðе удалоÑÑŒ выделить памÑÑ‚ÑŒ Ð´Ð»Ñ -maxsigcachesize: "%s" МиБ</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation type="unfinished">Ðевозможно привÑзатьÑÑ Ðº %s на Ñтом компьютере (bind вернул ошибку %s)</translation>
+ <translation type="unfinished">Ðевозможно привÑзатьÑÑ (bind) к %s на Ñтом компьютере (ошибка %s)</translation>
</message>
<message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation type="unfinished">Ðевозможно привÑзатьÑÑ Ðº %s на Ñтом компьютере. Возможно, %s уже запущен.</translation>
+ <translation type="unfinished">Ðевозможно привÑзатьÑÑ (bind) к %s на Ñтом компьютере. Возможно, %s уже запущен.</translation>
</message>
<message>
<source>Unable to create the PID file '%s': %s</source>
- <translation type="unfinished">Ðевозможно Ñоздать файл PID '%s': %s</translation>
+ <translation type="unfinished">Ðе удалоÑÑŒ Ñоздать PID-файл "%s": %s</translation>
+ </message>
+ <message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">Ðе удалоÑÑŒ найти UTXO Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ³Ð¾ входа</translation>
</message>
<message>
<source>Unable to generate initial keys</source>
@@ -963,8 +1190,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðе удаетÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚ÑŒ %s Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи</translation>
</message>
<message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">Ошибка при разборе параметра -maxuploadtarget: "%s"</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
- <translation type="unfinished">Ðевозможно запуÑтить HTTP-Ñервер. См. подробноÑти в журнале отладки.</translation>
+ <translation type="unfinished">Ðевозможно запуÑтить HTTP-Ñервер. ПодробноÑти в файле debug.log.</translation>
+ </message>
+ <message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">Ðе удалоÑÑŒ выгрузить кошелёк перед миграцией</translation>
</message>
<message>
<source>Unknown -blockfilterindex value %s.</source>
@@ -972,23 +1207,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unknown address type '%s'</source>
- <translation type="unfinished">ÐеизвеÑтный тип адреÑа '%s'</translation>
+ <translation type="unfinished">ÐеизвеÑтный тип адреÑа "%s"</translation>
</message>
<message>
<source>Unknown change type '%s'</source>
- <translation type="unfinished">ÐеизвеÑтный тип Ñдачи '%s'</translation>
+ <translation type="unfinished">ÐеизвеÑтный тип Ñдачи "%s"</translation>
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
- <translation type="unfinished">ÐеизвеÑÑ‚Ð½Ð°Ñ Ñеть указана в -onlynet: '%s'</translation>
+ <translation type="unfinished">Ð’ -onlynet указана неизвеÑÑ‚Ð½Ð°Ñ Ñеть: "%s"</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">ÐÐµÐ¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ñ Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° %s=%s.</translation>
+ <source>Unknown new rules activated (versionbit %i)</source>
+ <translation type="unfinished">Ð’ Ñилу вÑтупили неизвеÑтные правила (versionbit %i)</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Обновление базы данных UTXO</translation>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">Ðеподдерживаемый уровень подробноÑти Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° -loglevel=%s. ДоÑтупные значениÑ: %s.</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Ðеподдерживаемый уровень Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð° %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -996,15 +1235,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Verifying blocks…</source>
- <translation type="unfinished">Проверка блоков...</translation>
+ <translation type="unfinished">Проверка блоков…</translation>
</message>
<message>
<source>Verifying wallet(s)…</source>
- <translation type="unfinished">Проверка кошелька(ов)...</translation>
+ <translation type="unfinished">Проверка кошелька(ов)…</translation>
</message>
<message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
- <translation type="unfinished">Ðеобходимо перезапиÑать кошелёк, перезапуÑтите %s Ð´Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¸</translation>
+ <translation type="unfinished">Ðеобходимо перезапиÑать кошелёк. ПерезапуÑтите %s Ð´Ð»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ð¸</translation>
</message>
</context>
<context>
@@ -1015,7 +1254,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Show general overview of wallet</source>
- <translation type="unfinished">Отобразить оÑновное окно кошелька</translation>
+ <translation type="unfinished">Показать текущее ÑоÑтоÑние кошелька</translation>
</message>
<message>
<source>&amp;Transactions</source>
@@ -1058,6 +1297,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Создать новый кошелёк</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Свернуть</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Кошелёк:</translation>
</message>
@@ -1072,7 +1315,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation type="unfinished">Отправить ÑредÑтва на Биткоин адреÑ</translation>
+ <translation type="unfinished">Отправить ÑредÑтва на биткоин-адреÑ</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -1080,7 +1323,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
- <translation type="unfinished">Изменить пароль иÑпользуемый Ð´Ð»Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ°</translation>
+ <translation type="unfinished">Изменить парольную фразу, иÑпользуемую Ð´Ð»Ñ ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ°</translation>
</message>
<message>
<source>&amp;Send</source>
@@ -1092,11 +1335,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Options…</source>
- <translation type="unfinished">&amp;Параметры...</translation>
+ <translation type="unfinished">&amp;Параметры…</translation>
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
- <translation type="unfinished">&amp;Зашифровать Кошелёк...</translation>
+ <translation type="unfinished">&amp;Зашифровать кошелёк…</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
@@ -1104,47 +1347,47 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Backup Wallet…</source>
- <translation type="unfinished">&amp;Создать резервную копию кошелька...</translation>
+ <translation type="unfinished">&amp;Сделать резервную копию кошелька…</translation>
</message>
<message>
<source>&amp;Change Passphrase…</source>
- <translation type="unfinished">&amp;Изменить пароль...</translation>
+ <translation type="unfinished">&amp;Изменить парольную фразу…</translation>
</message>
<message>
<source>Sign &amp;message…</source>
- <translation type="unfinished">ПодпиÑать &amp;Ñообщение...</translation>
+ <translation type="unfinished">ПодпиÑать &amp;Ñообщение…</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">ПодпиÑать ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñвоими Биткоин кошельками, что-бы доказать, что вы ими владеете</translation>
+ <translation type="unfinished">ПодпиÑать Ñообщение биткоин-адреÑом, чтобы доказать, что вы им владеете</translation>
</message>
<message>
<source>&amp;Verify message…</source>
- <translation type="unfinished">&amp;Проверить Ñообщение</translation>
+ <translation type="unfinished">&amp;Проверить Ñообщение…</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation type="unfinished">ПроверÑйте ÑообщениÑ, чтобы убедитьÑÑ, что они подпиÑаны конкретными биткоин-адреÑами</translation>
+ <translation type="unfinished">Проверить подпиÑÑŒ ÑообщениÑ, чтобы убедитьÑÑ, что оно подпиÑано конкретным биткоин-адреÑом</translation>
</message>
<message>
<source>&amp;Load PSBT from file…</source>
- <translation type="unfinished">&amp;Загрузить PSBT из файла...</translation>
+ <translation type="unfinished">&amp;Загрузить PSBT из файла…</translation>
</message>
<message>
<source>Open &amp;URI…</source>
- <translation type="unfinished">О&amp;ткрыть URI...</translation>
+ <translation type="unfinished">Открыть &amp;URI…</translation>
</message>
<message>
<source>Close Wallet…</source>
- <translation type="unfinished">Закрыть кошелёк...</translation>
+ <translation type="unfinished">Закрыть кошелёк…</translation>
</message>
<message>
<source>Create Wallet…</source>
- <translation type="unfinished">Создать кошелёк...</translation>
+ <translation type="unfinished">Создать кошелёк…</translation>
</message>
<message>
<source>Close All Wallets…</source>
- <translation type="unfinished">Закрыть вÑе кошельки...</translation>
+ <translation type="unfinished">Закрыть вÑе кошельки…</translation>
</message>
<message>
<source>&amp;File</source>
@@ -1164,27 +1407,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Syncing Headers (%1%)…</source>
- <translation type="unfinished">Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² (%1%)...</translation>
+ <translation type="unfinished">Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² (%1%)…</translation>
</message>
<message>
<source>Synchronizing with network…</source>
- <translation type="unfinished">Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ Ñетью...</translation>
+ <translation type="unfinished">Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ Ñетью…</translation>
</message>
<message>
<source>Indexing blocks on disk…</source>
- <translation type="unfinished">ИндекÑÐ°Ñ†Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¾Ð² на диÑке...</translation>
+ <translation type="unfinished">ИндекÑÐ°Ñ†Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¾Ð² на диÑке…</translation>
</message>
<message>
<source>Processing blocks on disk…</source>
- <translation type="unfinished">Обработка блоков на диÑке...</translation>
+ <translation type="unfinished">Обработка блоков на диÑке…</translation>
</message>
<message>
<source>Reindexing blocks on disk…</source>
- <translation type="unfinished">ПереиндекÑÐ°Ñ†Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¾Ð² на диÑке...</translation>
+ <translation type="unfinished">ПереиндекÑÐ°Ñ†Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¾Ð² на диÑке…</translation>
</message>
<message>
<source>Connecting to peers…</source>
- <translation type="unfinished">Подключение к узлам...</translation>
+ <translation type="unfinished">Подключение к узлам…</translation>
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
@@ -1192,31 +1435,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
- <translation type="unfinished">Показать ÑпиÑок адреÑов, на которые были отправлены ÑредÑтва, и их метки</translation>
+ <translation type="unfinished">Показать ÑпиÑок иÑпользованных адреÑов отправки и меток</translation>
</message>
<message>
<source>Show the list of used receiving addresses and labels</source>
- <translation type="unfinished">Показать ÑпиÑок адреÑов, на которые были получены ÑредÑтва, и их метки</translation>
+ <translation type="unfinished">Показать ÑпиÑок иÑпользованных адреÑов Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¸ меток</translation>
</message>
<message>
<source>&amp;Command-line options</source>
- <translation type="unfinished">Параметры &amp;командной Ñтроки</translation>
+ <translation type="unfinished">&amp;Параметры командной Ñтроки</translation>
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>Обработан %n блок иÑтории транзакций.</numerusform>
+ <numerusform>Обработано %n блока иÑтории транзакций.</numerusform>
+ <numerusform>Обработано %n блоков иÑтории транзакций.</numerusform>
</translation>
</message>
<message>
<source>%1 behind</source>
- <translation type="unfinished">ОтÑтаём на %1</translation>
+ <translation type="unfinished">%1 позади</translation>
</message>
<message>
<source>Catching up…</source>
- <translation type="unfinished">СинхронизациÑ...</translation>
+ <translation type="unfinished">СинхронизациÑ…</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
@@ -1240,13 +1483,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Up to date</source>
- <translation type="unfinished">Синхронизировано</translation>
+ <translation type="unfinished">Синхронизированно</translation>
</message>
<message>
<source>Load Partially Signed Bitcoin Transaction</source>
<translation type="unfinished">Загрузить чаÑтично подпиÑанную биткоин-транзакцию (PSBT)</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">Загрузить PSBT из &amp;буфера обмена…</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Загрузить чаÑтично подпиÑанную биткоин-транзакцию из буфера обмена</translation>
</message>
@@ -1283,12 +1530,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Закрыть кошелёк</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">ВоÑÑтановить кошелёк…</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">ВоÑÑтановить кошелек из резервной копии</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Закрыть вÑе кошельки</translation>
</message>
<message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation type="unfinished">Показать помощь по %1, чтобы получить ÑпиÑок доÑтупных параметров командной Ñтроки</translation>
+ <translation type="unfinished">Показать Ñправку %1 Ñо ÑпиÑком доÑтупных параметров командной Ñтроки</translation>
</message>
<message>
<source>&amp;Mask values</source>
@@ -1307,12 +1564,32 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðет доÑтупных кошельков</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Данные кошелька</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Загрузить резервную копию кошелька</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">ВоÑÑтановить кошелёк</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Ðазвание кошелька</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Окно</translation>
</message>
<message>
<source>Zoom</source>
- <translation type="unfinished">МаÑштаб</translation>
+ <translation type="unfinished">Развернуть</translation>
</message>
<message>
<source>Main Window</source>
@@ -1322,13 +1599,21 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 клиент</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Скрыть</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">&amp;Показать</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>%n активное подключение к Ñети Bitcoin.</numerusform>
+ <numerusform>%n активных Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Ñети Bitcoin.</numerusform>
+ <numerusform>%n активных подключений к Ñети Bitcoin.</numerusform>
</translation>
</message>
<message>
@@ -1352,6 +1637,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Включить взаимодейÑтвие Ñ Ñетью</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">ПредÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² (%1%)…</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Ошибка: %1</translation>
</message>
@@ -1386,7 +1675,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>Label: %1
</source>
- <translation type="unfinished">Ярлык: %1
+ <translation type="unfinished">Метка: %1
</translation>
</message>
<message>
@@ -1487,7 +1776,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Received with label</source>
- <translation type="unfinished">Получено на метку</translation>
+ <translation type="unfinished">Получено Ñ Ð¼ÐµÑ‚ÐºÐ¾Ð¹</translation>
</message>
<message>
<source>Received with address</source>
@@ -1510,6 +1799,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Копировать Ñумму</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Копировать адреÑ</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копировать &amp;метку</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Копировать Ñ&amp;умму</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Скопировать &amp;ID транзакции и Ð¸Ð½Ð´ÐµÐºÑ Ð²Ñ‹Ð²Ð¾Ð´Ð°</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">З&amp;аблокировать неизраÑходованный оÑтаток</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">&amp;Разблокировать неизраÑходованный оÑтаток</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Копировать количеÑтво</translation>
</message>
@@ -1519,7 +1832,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Copy after fee</source>
- <translation type="unfinished">Копировать поÑле комиÑÑии</translation>
+ <translation type="unfinished">Копировать Ñумму поÑле комиÑÑии</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -1551,7 +1864,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation type="unfinished">Может менÑÑ‚ÑŒÑÑ +/- %1 Ñатоши за вход.</translation>
+ <translation type="unfinished">Может менÑÑ‚ÑŒÑÑ Ð½Ð° +/- %1 Ñатоши за каждый вход.</translation>
</message>
<message>
<source>(no label)</source>
@@ -1576,7 +1889,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
<extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
- <translation type="unfinished">Создание кошелька &lt;b&gt;%1&lt;/b&gt;...</translation>
+ <translation type="unfinished">Создание кошелька &lt;b&gt;%1&lt;/b&gt;…</translation>
</message>
<message>
<source>Create wallet failed</source>
@@ -1584,9 +1897,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Create wallet warning</source>
- <translation type="unfinished">Кошелёк Ñоздан</translation>
+ <translation type="unfinished">Предупреждение при Ñоздании кошелька</translation>
+ </message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Ðевозможно отобразить подпиÑантов</translation>
</message>
- </context>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Обнаружено Ñлишком много внешних подпиÑантов</translation>
+ </message>
+</context>
+<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">Загрузить кошельки</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">Загрузка кошельков…</translation>
+ </message>
+</context>
<context>
<name>OpenWalletActivity</name>
<message>
@@ -1609,7 +1943,35 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
<extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
- <translation type="unfinished">ОткрываетÑÑ ÐºÐ¾ÑˆÐµÐ»Ñ‘Ðº &lt;b&gt;%1&lt;/b&gt;...</translation>
+ <translation type="unfinished">ОткрываетÑÑ ÐºÐ¾ÑˆÐµÐ»Ñ‘Ðº &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+</context>
+<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">ВоÑÑтановить кошелёк</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">ВоÑÑтановление кошелька &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Ðе удалоÑÑŒ воÑÑтановить кошелек</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Предупреждение при воÑÑтановлении кошелька</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Сообщение при воÑÑтановлении кошелька</translation>
</message>
</context>
<context>
@@ -1632,7 +1994,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Are you sure you wish to close all wallets?</source>
- <translation type="unfinished">Ð’Ñ‹ уверенны, что хотите закрыть вÑе кошельки?</translation>
+ <translation type="unfinished">Ð’Ñ‹ уверены, что хотите закрыть вÑе кошельки?</translation>
</message>
</context>
<context>
@@ -1663,7 +2025,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<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">Отключить приватные ключи Ð´Ð»Ñ Ñтого кошелька. Ð’ кошельках Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡Ñ‘Ð½Ð½Ñ‹Ð¼Ð¸ приватными ключами не ÑохранÑÑŽÑ‚ÑÑ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ñ‹Ðµ ключи, в них Ð½ÐµÐ»ÑŒÐ·Ñ Ñоздать HD маÑтер-ключ или импортировать приватные ключи. Это удобно Ð´Ð»Ñ Ð½Ð°Ð±Ð»ÑŽÐ´Ð°ÑŽÑ‰Ð¸Ñ… кошельков.</translation>
+ <translation type="unfinished">Отключить приватные ключи Ð´Ð»Ñ Ñтого кошелька. Ð’ кошельках Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡Ñ‘Ð½Ð½Ñ‹Ð¼Ð¸ приватными ключами не ÑохранÑÑŽÑ‚ÑÑ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ñ‹Ðµ ключи, в них Ð½ÐµÐ»ÑŒÐ·Ñ Ñоздать HD маÑтер-ключ или импортировать приватные ключи. Это отличный вариант Ð´Ð»Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ¾Ð² Ð´Ð»Ñ Ð½Ð°Ð±Ð»ÑŽÐ´ÐµÐ½Ð¸Ñ Ð·Ð° баланÑом.</translation>
</message>
<message>
<source>Disable Private Keys</source>
@@ -1686,14 +2048,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ДеÑкрипторный кошелёк</translation>
</message>
<message>
+ <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>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">ВнешнÑÑ Ð¿Ð¾Ð´Ð¿Ð¸ÑÑ‹Ð²Ð°ÑŽÑ‰Ð°Ñ Ñторона</translation>
+ </message>
+ <message>
<source>Create</source>
<translation type="unfinished">Создать</translation>
</message>
<message>
<source>Compiled without sqlite support (required for descriptor wallets)</source>
- <translation type="unfinished">Скомпилирован без поддержки sqlite (необходимо Ð´Ð»Ñ Ð´ÐµÑкрипторных кошельков)</translation>
+ <translation type="unfinished">Скомпилирован без поддержки SQLite (он необходим Ð´Ð»Ñ Ð´ÐµÑкрипторных кошельков)</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Скомпилирован без поддержки внешней подпиÑи (требуетÑÑ Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ¹ подпиÑи)</translation>
</message>
- </context>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -1710,7 +2085,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation type="unfinished">ÐдреÑ, ÑвÑзанный Ñ Ñтой запиÑью адреÑной книги. Он может быть изменён только еÑли Ñто Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸.</translation>
+ <translation type="unfinished">ÐдреÑ, ÑвÑзанный Ñ Ñтой запиÑью адреÑной книги. ЕÑли Ñто Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸, его можно изменить.</translation>
</message>
<message>
<source>&amp;Address</source>
@@ -1718,15 +2093,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>New sending address</source>
- <translation type="unfinished">Ðовый Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸</translation>
+ <translation type="unfinished">Ðовый Ð°Ð´Ñ€ÐµÑ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸</translation>
</message>
<message>
<source>Edit receiving address</source>
- <translation type="unfinished">Изменить Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ</translation>
+ <translation type="unfinished">Изменить Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ</translation>
</message>
<message>
<source>Edit sending address</source>
- <translation type="unfinished">Изменить Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸</translation>
+ <translation type="unfinished">Изменить Ð°Ð´Ñ€ÐµÑ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸</translation>
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
@@ -1746,74 +2121,86 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>New key generation failed.</source>
- <translation type="unfinished">Произошла ошибка при генерации нового ключа.</translation>
+ <translation type="unfinished">Ðе удалоÑÑŒ Ñгенерировать новый ключ.</translation>
</message>
</context>
<context>
<name>FreespaceChecker</name>
<message>
<source>A new data directory will be created.</source>
- <translation type="unfinished">Будет Ñоздана Ð½Ð¾Ð²Ð°Ñ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ….</translation>
+ <translation type="unfinished">Будет Ñоздан новый каталог данных.</translation>
</message>
<message>
<source>name</source>
- <translation type="unfinished">имÑ</translation>
+ <translation type="unfinished">название</translation>
</message>
<message>
<source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation type="unfinished">Ð”Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ ÑƒÐ¶Ðµ ÑущеÑтвует. Добавьте %1, еÑли хотите Ñоздать здеÑÑŒ новую директорию.</translation>
+ <translation type="unfinished">Каталог уже ÑущеÑтвует. Добавьте %1, еÑли хотите Ñоздать здеÑÑŒ новый каталог.</translation>
</message>
<message>
<source>Path already exists, and is not a directory.</source>
- <translation type="unfinished">Данный путь уже ÑущеÑтвует, и Ñто не директориÑ.</translation>
+ <translation type="unfinished">Данный путь уже ÑущеÑтвует, и Ñто не каталог.</translation>
</message>
<message>
<source>Cannot create data directory here.</source>
- <translation type="unfinished">Ðевозможно Ñоздать директорию данных здеÑÑŒ.</translation>
+ <translation type="unfinished">Ðевозможно Ñоздать здеÑÑŒ каталог данных.</translation>
</message>
</context>
<context>
<name>Intro</name>
- <message>
- <source>Bitcoin</source>
- <translation type="unfinished">биткоин</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>%n ГБ меÑта доÑтупен</numerusform>
+ <numerusform>%n ГБ меÑта доÑтупно</numerusform>
+ <numerusform>%n ГБ меÑта доÑтупно</numerusform>
+ </translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(из необходимых %1 ГБ)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(из требуемого %n ГБ)</numerusform>
+ <numerusform>(из требуемых %n ГБ)</numerusform>
+ <numerusform>(из требуемых %n ГБ)</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(необходимо %1 ГБ Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ цепочки блоков)</translation>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n ГБ необходим Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ цепочки)</numerusform>
+ <numerusform>(%n ГБ необходимо Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ цепочки)</numerusform>
+ <numerusform>(%n ГБ необходимо Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¹ цепочки)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation type="unfinished">Ð’ Ñту директорию будет Ñохранено не менее %1 ГБ данных, и Ñо временем их объём будет увеличиватьÑÑ.</translation>
+ <translation type="unfinished">Ð’ Ñтот каталог будет Ñохранено не менее %1 ГБ данных, и Ñо временем их объём будет увеличиватьÑÑ.</translation>
</message>
<message>
<source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation type="unfinished">Ð’ Ñту директорию будет Ñохранено приблизительно %1 ГБ данных.</translation>
+ <translation type="unfinished">Ð’ Ñтот каталог будет Ñохранено приблизительно %1 ГБ данных.</translation>
</message>
<message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>(доÑтаточно Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¾Ð¹ копии возраÑтом %n день)</numerusform>
+ <numerusform>(доÑтаточно Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¾Ð¹ копии возраÑтом %n днÑ)</numerusform>
+ <numerusform>(доÑтаточно Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¾Ð¹ копии возраÑтом %n дней)</numerusform>
</translation>
</message>
<message>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation type="unfinished">%1 Ñкачает и Ñохранит копию цепочки блоков биткоина.</translation>
+ <translation type="unfinished">%1 Ñкачает и Ñохранит копию цепочки блоков Bitcoin.</translation>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation type="unfinished">Кошелёк также будет Ñохранен в Ñту директорию.</translation>
+ <translation type="unfinished">Кошелёк также будет Ñохранён в Ñтот каталог.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
- <translation type="unfinished">Ошибка: невозможно Ñоздать указанную директорию данных "%1".</translation>
+ <translation type="unfinished">Ошибка: не удалоÑÑŒ Ñоздать указанный каталог данных "%1".</translation>
</message>
<message>
<source>Error</source>
@@ -1832,10 +2219,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ПоÑкольку программа запущена впервые, вы можете выбрать, где %1 будет хранить Ñвои данные.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Когда вы нажмёте ОК, %1 начнет Ñкачивать и обрабатывать полную цепочку блоков %4а (%2 ГБ), Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ Ñамых первых транзакций в %3, когда %4 был изначально запущен.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Ограничить размер Ñохранённой цепочки блоков до</translation>
</message>
@@ -1852,16 +2235,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Эта Ð¿ÐµÑ€Ð²Ð¸Ñ‡Ð½Ð°Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¾Ñ‡ÐµÐ½ÑŒ требовательна к реÑурÑам и может выÑвить проблемы Ñ Ð°Ð¿Ð¿Ð°Ñ€Ð°Ñ‚Ð½Ñ‹Ð¼ обеÑпечением вашего компьютера, которые ранее оÑтавалиÑÑŒ незамеченными. Каждый раз, когда вы запуÑкаете %1, Ñкачивание будет продолжено Ñ Ð¼ÐµÑта оÑтановки.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">Когда вы нажмете ОК, %1 начнет загружать и обрабатывать полную цепочку блоков %4 (%2 ГБ) Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ Ñамых ранних транзакций в %3, когда %4 был первоначально запущен.</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation type="unfinished">ЕÑли вы решили ограничить объём хранимого блокчейна (обрезка), вÑе иÑторичеÑкие данные вÑÑ‘ равно необходимо Ñкачать и обработать, но поÑле Ñтого они будут удалены Ð´Ð»Ñ Ñкономии меÑта на диÑке.</translation>
+ <translation type="unfinished">ЕÑли вы решили ограничить (обрезать) объём хранимой цепи блоков, вÑе ранние данные вÑÑ‘ равно должны быть Ñкачаны и обработаны. ПоÑле обработки они будут удалены Ñ Ñ†ÐµÐ»ÑŒÑŽ Ñкономии меÑта на диÑке.</translation>
</message>
<message>
<source>Use the default data directory</source>
- <translation type="unfinished">ИÑпользовать Ñтандартную директорию данных</translation>
+ <translation type="unfinished">ИÑпользовать каталог данных по умолчанию</translation>
</message>
<message>
<source>Use a custom data directory:</source>
- <translation type="unfinished">ИÑпользовать пользовательÑкую директорию данных</translation>
+ <translation type="unfinished">ИÑпользовать пользовательÑкий каталог данных:</translation>
</message>
</context>
<context>
@@ -1876,14 +2263,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Command-line options</source>
- <translation type="unfinished">Параметры командной Ñтроки</translation>
+ <translation type="unfinished">Опции командной Ñтроки</translation>
</message>
</context>
<context>
<name>ShutdownWindow</name>
<message>
<source>%1 is shutting down…</source>
- <translation type="unfinished">%1 завершает работу...</translation>
+ <translation type="unfinished">%1 выключаетÑÑ…</translation>
</message>
<message>
<source>Do not shut down the computer until this window disappears.</source>
@@ -1898,11 +2285,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation type="unfinished">Ðедавние транзакции могут быть пока не видны, и поÑтому отображаемый Ð±Ð°Ð»Ð°Ð½Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ кошелька может быть неверным. Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñтанет верной поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñинхронизации Ñ Ñетью биткоина, прогреÑÑ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ вы можете видеть ниже.</translation>
+ <translation type="unfinished">Ðедавние транзакции могут быть пока не видны, и поÑтому отображаемый Ð±Ð°Ð»Ð°Ð½Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ кошелька может быть неверным. Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñтанет верной поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñинхронизации Ñ Ñетью Bitcoin. ПрогреÑÑ Ñинхронизации вы можете видеть Ñнизу.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation type="unfinished">Попытка потратить ÑредÑтва, затронутые не видными пока транзакциÑми, будет отклонена Ñетью.</translation>
+ <translation type="unfinished">Попытка потратить ÑредÑтва, иÑпользованные в транзакциÑÑ…, которые ещё не Ñинхронизированы, будет отклонена Ñетью.</translation>
</message>
<message>
<source>Number of blocks left</source>
@@ -1910,11 +2297,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unknown…</source>
- <translation type="unfinished">ÐеизвеÑтно...</translation>
+ <translation type="unfinished">ÐеизвеÑтно…</translation>
</message>
<message>
<source>calculating…</source>
- <translation type="unfinished">вычиÑлÑетÑÑ...</translation>
+ <translation type="unfinished">вычиÑлÑетÑÑ…</translation>
</message>
<message>
<source>Last block time</source>
@@ -1930,7 +2317,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Estimated time left until synced</source>
- <translation type="unfinished">РаÑчётное Ð²Ñ€ÐµÐ¼Ñ Ð´Ð¾ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñинхронизации</translation>
+ <translation type="unfinished">РаÑчетное Ð²Ñ€ÐµÐ¼Ñ Ð´Ð¾ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñинхронизации</translation>
</message>
<message>
<source>Hide</source>
@@ -1938,7 +2325,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Esc</source>
- <translation type="unfinished">Выйти</translation>
+ <translation type="unfinished">Выход</translation>
</message>
<message>
<source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
@@ -1946,14 +2333,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
- <translation type="unfinished">ÐеизвеÑтно. СинхронизируютÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¸ (%1, %2%)...</translation>
+ <translation type="unfinished">ÐеизвеÑтно. Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² (%1, %2%)…</translation>
+ </message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">ÐеизвеÑтно. ПредÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² (%1, %2%)…</translation>
</message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
<source>Open bitcoin URI</source>
- <translation type="unfinished">Открыть URI биткоина</translation>
+ <translation type="unfinished">Открыть URI bitcoin</translation>
</message>
<message>
<source>Paste address from clipboard</source>
@@ -1969,11 +2360,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Main</source>
- <translation type="unfinished">&amp;Главные</translation>
+ <translation type="unfinished">&amp;ОÑновное</translation>
</message>
<message>
<source>Automatically start %1 after logging in to the system.</source>
- <translation type="unfinished">ÐвтоматичеÑки запуÑкать %1 поÑле входа в ÑиÑтему.</translation>
+ <translation type="unfinished">ÐвтоматичеÑки запуÑкать %1поÑле входа в ÑиÑтему.</translation>
</message>
<message>
<source>&amp;Start %1 on system login</source>
@@ -1997,15 +2388,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
- <translation type="unfinished">Показывает, иÑпользуетÑÑ Ð»Ð¸ прокÑи SOCKS5 по умолчанию Ð´Ð»Ñ Ð´Ð¾Ñтупа к узлам через Ñтот тип Ñети.</translation>
+ <translation type="unfinished">ИÑпользовать SOCKS5 прокÑи Ð´Ð»Ñ Ð´Ð¾Ñтупа к узлам через Ñтот тип Ñети.</translation>
</message>
<message>
<source>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>
<translation type="unfinished">Сворачивать вмеÑто выхода из Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ закрытии окна. ЕÑли данный параметр включён, приложение закроетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ поÑле Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ñ "Выход" в меню.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Параметры командной Ñтроки, которые переопределили параметры из Ñтого окна:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
- <translation type="unfinished">Открывает файл конфигурации %1 из рабочей директории.</translation>
+ <translation type="unfinished">Открывает файл конфигурации %1 из рабочего каталога.</translation>
</message>
<message>
<source>Open Configuration File</source>
@@ -2025,7 +2420,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Prune &amp;block storage to</source>
- <translation type="unfinished">Обрезать объём хранимых блоков до</translation>
+ <translation type="unfinished">Обрезать &amp;объём хранимых блоков до</translation>
</message>
<message>
<source>GB</source>
@@ -2036,28 +2431,48 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Возврат Ñтой наÑтройки в прежнее значение потребует повторного ÑÐºÐ°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ Ð²Ñей цепочки блоков.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">МакÑимальный размер кÑша базы данных. Большой размер кÑша может уÑкорить Ñинхронизацию, поÑле чего уже оÑобой роли не играет. Уменьшение размера кÑша уменьшит иÑпользование памÑти. ÐеиÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÐµÐ¼Ð°Ñ Ð¿Ð°Ð¼ÑÑ‚ÑŒ mempool иÑпользуетÑÑ ÑовмеÑтно Ð´Ð»Ñ Ñтого кÑша.</translation>
+ </message>
+ <message>
<source>MiB</source>
<translation type="unfinished">МиБ</translation>
</message>
<message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">ЧиÑло потоков проверки Ñкриптов. Отрицательные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð·Ð°Ð´Ð°ÑŽÑ‚ чиÑло Ñдер ЦП, которые не будут нагружатьÑÑ (оÑтанутÑÑ Ñвободны).</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = автоматичеÑки, &lt;0 = оÑтавить Ñтолько Ñдер Ñвободными)</translation>
</message>
<message>
<source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
<extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
- <translation type="unfinished">Это позволÑет вам или Ñторонней программе взаимодейÑтвовать Ñ Ñтим узлом через командную Ñтроку и команды JSON-RPC</translation>
+ <translation type="unfinished">Разрешает вам или Ñторонней программе взаимодейÑтвовать Ñ Ñтим узлом через командную Ñтроку и команды JSON-RPC.</translation>
</message>
<message>
<source>Enable R&amp;PC server</source>
<extracomment>An Options window setting to enable the RPC server.</extracomment>
- <translation type="unfinished">Включить R&amp;PC Ñервер</translation>
+ <translation type="unfinished">Включить RPC &amp;Ñервер</translation>
</message>
<message>
<source>W&amp;allet</source>
<translation type="unfinished">&amp;Кошелёк</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Вычитать комиÑÑию из Ñуммы по умолчанию или нет.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">ВычеÑÑ‚ÑŒ &amp;комиÑÑию из Ñуммы</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">ЭкÑпертные наÑтройки</translation>
</message>
@@ -2067,13 +2482,35 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>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>
- <translation type="unfinished">ЕÑли вы отключите трату неподтверждённой Ñдачи, Ñдачу от транзакции Ð½ÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ иÑпользвать до тех пор, пока у Ñтой транзакции не будет Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одного подтверждениÑ. Это также влиÑет на раÑчёт вашего баланÑа.</translation>
+ <translation type="unfinished">ЕÑли вы отключите трату неподтверждённой Ñдачи, Ñдачу от транзакции Ð½ÐµÐ»ÑŒÐ·Ñ Ð±ÑƒÐ´ÐµÑ‚ иÑпользовать до тех пор, пока у Ñтой транзакции не будет Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одного подтверждениÑ. Это также влиÑет на раÑчёт вашего баланÑа.</translation>
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
<translation type="unfinished">&amp;Тратить неподтверждённую Ñдачу</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Включить управление чаÑтично подпиÑанными транзакциÑми (PSBT)</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Показать Ñлементы ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‡Ð°Ñтично подпиÑанными биткоин-транзакциÑми (PSBT)</translation>
+ </message>
+ <message>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">Внешний подпиÑант (например, аппаратный кошелёк)</translation>
+ </message>
+ <message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">&amp;Внешний Ñкрипт Ð´Ð»Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñи</translation>
+ </message>
+ <message>
+ <source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
+ <translation type="unfinished">Путь к Ñкрипту, ÑовмеÑтимому Ñ Bitcoin Core (напр. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Внимание: оÑтерегайтеÑÑŒ вредоноÑных Ñкриптов!</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">ÐвтоматичеÑки открыть порт биткоин-клиента на маршрутизаторе. Работает, еÑли ваш маршрутизатор поддерживает UPnP, и Ð´Ð°Ð½Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð½Ð° нём включена.</translation>
</message>
@@ -2083,7 +2520,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>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>
- <translation type="unfinished">ÐвтоматичеÑки открыть порт биткоин-клиента на роутере. Работает? еÑли ваш роутер поддерживает NAT-PMP, и Ð´Ð°Ð½Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð½Ð° нём включена. Внешний порт может быть Ñлучайным.</translation>
+ <translation type="unfinished">ÐвтоматичеÑки открыть порт биткоин-клиента на роутере. Сработает только еÑли ваш роутер поддерживает NAT-PMP, и Ð´Ð°Ð½Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð½Ð° нём включена. Внешний порт может быть Ñлучайным.</translation>
</message>
<message>
<source>Map port using NA&amp;T-PMP</source>
@@ -2095,11 +2532,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Allow incomin&amp;g connections</source>
- <translation type="unfinished">Разрешить входÑщие ÑоединениÑ</translation>
+ <translation type="unfinished">Разрешить &amp;входÑщие ÑоединениÑ</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation type="unfinished">ПодключитьÑÑ Ðº Ñети биткоина через прокÑи SOCKS5.</translation>
+ <translation type="unfinished">ПодключитьÑÑ Ðº Ñети Bitcoin через SOCKS5 прокÑи.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
@@ -2107,7 +2544,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Proxy &amp;IP:</source>
- <translation type="unfinished">IP прокÑи:</translation>
+ <translation type="unfinished">IP &amp;прокÑи:</translation>
</message>
<message>
<source>&amp;Port:</source>
@@ -2115,11 +2552,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Port of the proxy (e.g. 9050)</source>
- <translation type="unfinished">Порт прокÑи: (напр. 9050)</translation>
+ <translation type="unfinished">Порт прокÑи (например, 9050)</translation>
</message>
<message>
<source>Used for reaching peers via:</source>
- <translation type="unfinished">ИÑпользуетÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº узлам по:</translation>
+ <translation type="unfinished">ИÑпользовать Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº узлам по:</translation>
</message>
<message>
<source>&amp;Window</source>
@@ -2151,11 +2588,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>User Interface &amp;language:</source>
- <translation type="unfinished">Язык пользовательÑкого интерфейÑа:</translation>
+ <translation type="unfinished">Язык &amp;интерфейÑа:</translation>
</message>
<message>
<source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation type="unfinished">ЗдеÑÑŒ можно выбрать Ñзык пользовательÑкого интерфейÑа. Параметры будут применены поÑле перезапуÑка %1</translation>
+ <translation type="unfinished">ЗдеÑÑŒ можно выбрать Ñзык пользовательÑкого интерфейÑа. Язык будет изменён поÑле перезапуÑка %1.</translation>
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
@@ -2166,16 +2603,24 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Выберите единицу измерениÑ, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ показана по умолчанию в интерфейÑе и при отправке монет.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Сторонние URL-адреÑа (например, на обозреватель блоков), которые будут показаны на вкладке транзакций в контекÑтном меню. %s в URL будет заменён на Ñ…Ñш транзакции. ÐеÑколько адреÑов разделÑÑŽÑ‚ÑÑ Ð´Ñ€ÑƒÐ³ от друга вертикальной чертой |.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;СÑылки на транзакции на Ñторонних ÑервиÑах</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
- <translation type="unfinished">Показывать ли параметры ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð½ÐµÑ‚Ð°Ð¼Ð¸.</translation>
+ <translation type="unfinished">Показывать параметры ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð½ÐµÑ‚Ð°Ð¼Ð¸.</translation>
</message>
<message>
<source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
- <translation type="unfinished">ПодключатьÑÑ Ðº Ñети биткоина через отдельный прокÑи SOCKS5 Ð´Ð»Ñ Ñкрытых ÑервиÑов Tor.</translation>
+ <translation type="unfinished">ПодключатьÑÑ Ðº Ñети Bitcoin через отдельный SOCKS5 прокÑи Ð´Ð»Ñ Ñкрытых ÑервиÑов Tor.</translation>
</message>
<message>
<source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
- <translation type="unfinished">ИÑпользовать отдельный прокÑи SOCKS&amp;5 Ð´Ð»Ñ ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ ÑƒÐ·Ð»Ð°Ð¼Ð¸ через Ñкрытые ÑервиÑÑ‹ Tor:</translation>
+ <translation type="unfinished">ИÑпользовать &amp;отдельный прокÑи SOCKS5 Ð´Ð»Ñ ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ñ ÑƒÐ·Ð»Ð°Ð¼Ð¸ через Ñкрытые ÑервиÑÑ‹ Tor:</translation>
</message>
<message>
<source>Monospaced font in the Overview tab:</source>
@@ -2187,11 +2632,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>closest matching "%1"</source>
- <translation type="unfinished">ближайшее Ñовпадение "%1"</translation>
- </message>
- <message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Параметры, уÑтановленные в Ñтом диалоговом окне, были переопределены командной Ñтрокой или в файле конфигурации:</translation>
+ <translation type="unfinished">Ñамый похожий ÑиÑтемный "%1"</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -2202,23 +2643,36 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">О&amp;тмена</translation>
</message>
<message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Скомпилирован без поддержки внешней подпиÑи (требуетÑÑ Ð´Ð»Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ¹ подпиÑи)</translation>
+ </message>
+ <message>
<source>default</source>
<translation type="unfinished">по умолчанию</translation>
</message>
<message>
<source>none</source>
- <translation type="unfinished">ни один</translation>
+ <translation type="unfinished">ни одного</translation>
</message>
<message>
<source>Confirm options reset</source>
- <translation type="unfinished">Подтвердить ÑÐ±Ñ€Ð¾Ñ Ð¾Ð¿Ñ†Ð¸Ð¹</translation>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
+ <translation type="unfinished">Подтверждение ÑброÑа наÑтроек</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Ð”Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ð¸Ð¸ изменений необходим перезапуÑк клиента.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Ð ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ… наÑтроек будет Ñохранена в "%1".</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Клиент будет закрыт. Продолжить?</translation>
</message>
<message>
@@ -2257,6 +2711,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Ðе удалоÑÑŒ прочитать наÑтройку "%1", %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2264,11 +2725,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>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>
- <translation type="unfinished">ÐŸÐ¾ÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть уÑтаревшей. Ваш кошелёк автоматичеÑки ÑинхронизируетÑÑ Ñ Ñетью биткоина поÑле подключениÑ, но Ñтот процеÑÑ Ð¿Ð¾ÐºÐ° не завершён.</translation>
+ <translation type="unfinished">ÐžÑ‚Ð¾Ð±Ñ€Ð°Ð¶Ð°ÐµÐ¼Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть уÑтаревшей. Ваш кошелёк автоматичеÑки ÑинхронизируетÑÑ Ñ Ñетью Bitcoin поÑле подключениÑ, и Ñтот процеÑÑ Ð¿Ð¾ÐºÐ° не завершён.</translation>
</message>
<message>
<source>Watch-only:</source>
- <translation type="unfinished">Только наблюдение:</translation>
+ <translation type="unfinished">Только проÑмотр:</translation>
</message>
<message>
<source>Available:</source>
@@ -2284,7 +2745,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation type="unfinished">ÐžÐ±Ñ‰Ð°Ñ Ñумма вÑех транзакций, которые ещё не подтверждены и не учитываютÑÑ Ð² баланÑе, который можно раÑходовать</translation>
+ <translation type="unfinished">Сумма по неподтверждённым транзакциÑм. Они не учитываютÑÑ Ð² баланÑе, который можно раÑходовать</translation>
</message>
<message>
<source>Immature:</source>
@@ -2332,7 +2793,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
- <translation type="unfinished">Включён режим приватноÑти Ð´Ð»Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ¸ обзора. Чтобы показать данные, отключите пункт ÐаÑтройки -&gt; Скрыть значениÑ.</translation>
+ <translation type="unfinished">Включён режим приватноÑти Ð´Ð»Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ¸ Обзор. Чтобы показать данные, Ñнимите отметку Ñ Ð¿ÑƒÐ½ÐºÑ‚Ð° ÐаÑтройки -&gt; Скрыть значениÑ.</translation>
</message>
</context>
<context>
@@ -2355,7 +2816,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Save…</source>
- <translation type="unfinished">Сохранить...</translation>
+ <translation type="unfinished">Сохранить…</translation>
</message>
<message>
<source>Close</source>
@@ -2447,6 +2908,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Транзакции требуетÑÑ Ð¿Ð¾ крайней мере ещё одна подпиÑÑŒ.</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Ðо ни один кошелек не загружен.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Ðо Ñтот кошелёк не может подпиÑывать транзакции.)</translation>
</message>
@@ -2456,7 +2921,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Transaction is fully signed and ready for broadcast.</source>
- <translation type="unfinished">Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ Ð¿Ð¾Ð»Ð½Ð¾Ñтью подпиÑана, и готова к отправке.</translation>
+ <translation type="unfinished">Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ Ð¿Ð¾Ð»Ð½Ð¾Ñтью подпиÑана и готова к отправке.</translation>
</message>
<message>
<source>Transaction status is unknown.</source>
@@ -2479,19 +2944,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation type="unfinished">«bitcoin://» — Ñто неверный URI. ИÑпользуйте вмеÑто него «bitcoin:».</translation>
+ <translation type="unfinished">"bitcoin://" — Ñто неверный URI. ИÑпользуйте вмеÑто него "bitcoin:".</translation>
</message>
<message>
<source>Cannot process payment request because BIP70 is not supported.
Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
<translation type="unfinished">Ðе удалоÑÑŒ обработать транзакцию, потому что BIP70 не поддерживаетÑÑ.
-Из-за широко раÑпроÑтранённых уÑзвимоÑтей в BIP70 наÑтоÑтельно рекомендуетÑÑ Ð¸Ð³Ð½Ð¾Ñ€Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ любые инÑтрукции продавцов Ñменить кошелёк.
+Из-за широко раÑпроÑтранённых уÑзвимоÑтей в BIP70, наÑтоÑтельно рекомендуетÑÑ Ð¸Ð³Ð½Ð¾Ñ€Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ любые инÑтрукции продавцов Ñменить кошелёк.
ЕÑли вы получили Ñту ошибку, вам Ñледует попроÑить у продавца URI, ÑовмеÑтимый Ñ BIP21.</translation>
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation type="unfinished">Ðе удалоÑÑŒ обработать URI! Это может быть вызвано тем, что биткоин-Ð°Ð´Ñ€ÐµÑ Ð½ÐµÐ²ÐµÑ€ÐµÐ½ или параметры URI неправильно Ñформированы.</translation>
+ <translation type="unfinished">Ðе удалоÑÑŒ обработать URI! Это может быть вызвано тем, что биткоин-Ð°Ð´Ñ€ÐµÑ Ð½ÐµÐ²ÐµÑ€ÐµÐ½ или параметры URI Ñформированы неправильно.</translation>
</message>
<message>
<source>Payment request file handling</source>
@@ -2508,7 +2973,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<message>
<source>Ping</source>
<extracomment>Title of Peers Table column which indicates the current latency of the connection with the peer.</extracomment>
- <translation type="unfinished">Отклик</translation>
+ <translation type="unfinished">Пинг</translation>
</message>
<message>
<source>Peer</source>
@@ -2516,6 +2981,11 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">Узел</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">ВозраÑÑ‚</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Ðаправление</translation>
@@ -2560,7 +3030,7 @@ If you are receiving this error you should request the merchant provide a BIP21
<name>QRImageWidget</name>
<message>
<source>&amp;Save Image…</source>
- <translation type="unfinished">&amp;Сохранить изображение...</translation>
+ <translation type="unfinished">&amp;Сохранить изображение…</translation>
</message>
<message>
<source>&amp;Copy Image</source>
@@ -2568,7 +3038,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation type="unfinished">ПолучившийÑÑ URI Ñлишком длинный, попробуйте Ñократить текÑÑ‚ метки / ÑообщениÑ.</translation>
+ <translation type="unfinished">ПолучившийÑÑ URI Ñлишком длинный, попробуйте Ñократить текÑÑ‚ метки или ÑообщениÑ.</translation>
</message>
<message>
<source>Error encoding URI into QR Code.</source>
@@ -2576,7 +3046,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>QR code support not available.</source>
- <translation type="unfinished">Поддержка QR кодов недоÑтупна.</translation>
+ <translation type="unfinished">Поддержка QR-кодов недоÑтупна.</translation>
</message>
<message>
<source>Save QR Code</source>
@@ -2604,7 +3074,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>General</source>
- <translation type="unfinished">Общий</translation>
+ <translation type="unfinished">Общие</translation>
</message>
<message>
<source>Datadir</source>
@@ -2612,7 +3082,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>To specify a non-default location of the data directory use the '%1' option.</source>
- <translation type="unfinished">Чтобы указать неÑтандартное раÑположение директории Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ…, иÑпользуйте параметр '%1'.</translation>
+ <translation type="unfinished">Чтобы указать неÑтандартное раÑположение каталога данных, иÑпользуйте параметр "%1".</translation>
</message>
<message>
<source>Blocksdir</source>
@@ -2620,7 +3090,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>To specify a non-default location of the blocks directory use the '%1' option.</source>
- <translation type="unfinished">Чтобы указать неÑтандартное раÑположение директории Ð´Ð»Ñ Ð±Ð»Ð¾ÐºÐ¾Ð², иÑпользуйте параметр '%1'.</translation>
+ <translation type="unfinished">Чтобы указать неÑтандартное раÑположение каталога блоков, иÑпользуйте параметр "%1".</translation>
</message>
<message>
<source>Startup time</source>
@@ -2664,7 +3134,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>&amp;Reset</source>
- <translation type="unfinished">&amp;СброÑить</translation>
+ <translation type="unfinished">&amp;СброÑ</translation>
</message>
<message>
<source>Received</source>
@@ -2684,7 +3154,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Select a peer to view detailed information.</source>
- <translation type="unfinished">Выберите узел Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра детальной информации.</translation>
+ <translation type="unfinished">Выберите узел Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра подробноÑтей.</translation>
</message>
<message>
<source>Version</source>
@@ -2703,6 +3173,10 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">Синхронизировано блоков</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">ПоÑледнÑÑ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">ÐŸÐ¾Ð´ÐºÐ»ÑŽÑ‡Ñ‘Ð½Ð½Ð°Ñ Ð°Ð²Ñ‚Ð¾Ð½Ð¾Ð¼Ð½Ð°Ñ ÑиÑтема, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÐµÐ¼Ð°Ñ Ð´Ð»Ñ Ð´Ð¸Ð²ÐµÑ€Ñификации узлов, к которым производитÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ðµ.</translation>
</message>
@@ -2711,12 +3185,42 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">ÐŸÐ¾Ð´ÐºÐ»ÑŽÑ‡Ñ‘Ð½Ð½Ð°Ñ ÐС</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Передаем ли мы адреÑа Ñтому узлу.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">РетранÑлÑтор адреÑов</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">КоличеÑтво адреÑов, полученных от Ñтого узла, которые были обработаны (за иÑключением адреÑов, отброшенных из-за ограничений по чаÑтоте).</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">КоличеÑтво адреÑов, полученных от Ñтого узла, которые были отброшены (не обработаны) из-за ограничений по чаÑтоте.</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Обработанные адреÑа</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Отброшенные адреÑа</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">ПользовательÑкий агент</translation>
</message>
<message>
<source>Node window</source>
- <translation type="unfinished">Окно ноды</translation>
+ <translation type="unfinished">Окно узла</translation>
</message>
<message>
<source>Current block height</source>
@@ -2724,7 +3228,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
- <translation type="unfinished">Открыть файл журнала отладки %1 из текущей директории данных. Ð”Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ñ… файлов журнала Ñто может занÑÑ‚ÑŒ неÑколько Ñекунд.</translation>
+ <translation type="unfinished">Открыть файл журнала отладки %1 из текущего каталога данных. Ð”Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ñ… файлов журнала Ñто может занÑÑ‚ÑŒ неÑколько Ñекунд.</translation>
</message>
<message>
<source>Decrease font size</source>
@@ -2752,7 +3256,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Services</source>
- <translation type="unfinished">СервиÑÑ‹</translation>
+ <translation type="unfinished">Службы</translation>
</message>
<message>
<source>Whether the peer requested us to relay transactions.</source>
@@ -2776,7 +3280,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
- <translation type="unfinished">Ð’Ñ€ÐµÐ¼Ñ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ блока, прошедшего базовую проверку, от Ñтого узла</translation>
+ <translation type="unfinished">Ð’Ñ€ÐµÐ¼Ñ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ блока, прошедшего базовую проверку, от Ñтого узла.</translation>
</message>
<message>
<source>Last Block</source>
@@ -2785,15 +3289,15 @@ If you are receiving this error you should request the merchant provide a BIP21
<message>
<source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
<extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
- <translation type="unfinished">Ð’Ñ€ÐµÐ¼Ñ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° принÑÑ‚Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð¹ транзакции в наш мемпул от Ñтого узла.</translation>
+ <translation type="unfinished">Ð’Ñ€ÐµÐ¼Ñ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° принÑÑ‚Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð¹ транзакции в наш mempool от Ñтого узла.</translation>
</message>
<message>
<source>Last Send</source>
- <translation type="unfinished">ПоÑл. Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸</translation>
+ <translation type="unfinished">ПоÑледнее Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚Ð¿Ñ€Ð°Ð²ÐºÐ¸</translation>
</message>
<message>
<source>Last Receive</source>
- <translation type="unfinished">ПоÑл. Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ</translation>
+ <translation type="unfinished">ПоÑледнее Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ</translation>
</message>
<message>
<source>Ping Time</source>
@@ -2801,7 +3305,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>The duration of a currently outstanding ping.</source>
- <translation type="unfinished">ПродолжительноÑÑ‚ÑŒ текущего времени отклика.</translation>
+ <translation type="unfinished">Задержка между запроÑом к узлу и ответом от него.</translation>
</message>
<message>
<source>Ping Wait</source>
@@ -2809,7 +3313,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Min Ping</source>
- <translation type="unfinished">Мин. Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ÐºÐ»Ð¸ÐºÐ°</translation>
+ <translation type="unfinished">Минимальное Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ÐºÐ»Ð¸ÐºÐ°</translation>
</message>
<message>
<source>Time Offset</source>
@@ -2894,6 +3398,11 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">широкополоÑный передатчик не выбран</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;Копировать адреÑ</translation>
+ </message>
+ <message>
<source>&amp;Disconnect</source>
<translation type="unfinished">О&amp;тключитьÑÑ</translation>
</message>
@@ -2902,6 +3411,10 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">1 &amp;чаÑ</translation>
</message>
<message>
+ <source>1 d&amp;ay</source>
+ <translation type="unfinished">1 &amp;день</translation>
+ </message>
+ <message>
<source>1 &amp;week</source>
<translation type="unfinished">1 &amp;неделÑ</translation>
</message>
@@ -2910,6 +3423,11 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">1 &amp;год</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">&amp;Копировать IP или маÑку подÑети</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">&amp;Разбанить</translation>
</message>
@@ -2935,17 +3453,17 @@ 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>
<extracomment>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.</extracomment>
<translation type="unfinished">Добро пожаловать в RPC-конÑоль %1.
-ИÑпользуйте Ñтрелки вверх и вниз, чтобы перемещатьÑÑ Ð¿Ð¾ иÑтории и %2, чтобы очиÑтить Ñкране.
+ИÑпользуйте Ñтрелки вверх и вниз, чтобы перемещатьÑÑ Ð¿Ð¾ иÑтории и %2, чтобы очиÑтить Ñкран.
Чтобы увеличить или уменьшить размер шрифта, нажмите %3 или %4.
Ðаберите %5, чтобы получить ÑпиÑок доÑтупных команд.
Чтобы получить больше информации об Ñтой конÑоли, наберите %6.
-%7Ð’ÐИМÐÐИЕ: мошенники очень чаÑто проÑÑÑ‚ пользователей вводить здеÑÑŒ различные команды и таким образом крадут Ñодержимое кошельков. Ðе иÑпользуйте Ñту конÑоль, еÑли не полноÑтью понимаете поÑледÑÑ‚Ð²Ð¸Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ команды.%8</translation>
+%7Ð’ÐИМÐÐИЕ: Мошенники очень чаÑто проÑÑÑ‚ пользователей вводить здеÑÑŒ различные команды и таким образом крадут Ñодержимое кошельков. Ðе иÑпользуйте Ñту конÑоль, еÑли не полноÑтью понимаете поÑледÑÑ‚Ð²Ð¸Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ команды.%8</translation>
</message>
<message>
<source>Executing…</source>
<extracomment>A console message indicating an entered command is currently being executed.</extracomment>
- <translation type="unfinished">ВыполнÑетÑÑ...</translation>
+ <translation type="unfinished">ВыполнÑетÑÑ…</translation>
</message>
<message>
<source>(peer: %1)</source>
@@ -2953,7 +3471,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>via %1</source>
- <translation type="unfinished">Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ %1</translation>
+ <translation type="unfinished">через %1</translation>
</message>
<message>
<source>Yes</source>
@@ -2965,11 +3483,11 @@ For more information on using this console, type %6.
</message>
<message>
<source>To</source>
- <translation type="unfinished">Кому</translation>
+ <translation type="unfinished">От наÑ</translation>
</message>
<message>
<source>From</source>
- <translation type="unfinished">От</translation>
+ <translation type="unfinished">К нам</translation>
</message>
<message>
<source>Ban for</source>
@@ -3000,11 +3518,11 @@ For more information on using this console, type %6.
</message>
<message>
<source>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>
- <translation type="unfinished">ÐеобÑзательное Ñообщение Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа платежа, которое будет показано при открытии запроÑа. Внимание: Ñто Ñообщение не будет отправлено вмеÑте Ñ Ð¿Ð»Ð°Ñ‚ÐµÐ¶Ð¾Ð¼ через Ñеть биткоина.</translation>
+ <translation type="unfinished">ÐеобÑзательное Ñообщение Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа платежа, которое будет показано при открытии запроÑа. Внимание: Ñто Ñообщение не будет отправлено вмеÑте Ñ Ð¿Ð»Ð°Ñ‚ÐµÐ¶Ð¾Ð¼ через Ñеть Bitcoin.</translation>
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
- <translation type="unfinished">Ð”Ð»Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ адреÑа Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ добавить метку.</translation>
+ <translation type="unfinished">ÐеобÑÐ·Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¼ÐµÑ‚ÐºÐ° Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ адреÑа получениÑ.</translation>
</message>
<message>
<source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
@@ -3012,11 +3530,11 @@ For more information on using this console, type %6.
</message>
<message>
<source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation type="unfinished">Можно указать Ñумму, платёж на которую вы запрашиваете. ОÑтавьте пуÑтой или введите ноль, чтобы не запрашивать определённую Ñумму.</translation>
+ <translation type="unfinished">Можно указать Ñумму, которую вы хотите запроÑить. ОÑтавьте поле пуÑтым или введите ноль, еÑли не хотите запрашивать конкретную Ñумму.</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">Можно указать метку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ приÑвоена новому адреÑу Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ (чтобы вы могли идентифицировать выÑтавленный Ñчёт). Также она приÑоединÑетÑÑ Ðº запроÑу платежа.</translation>
+ <translation type="unfinished">Можно указать метку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ приÑвоена новому адреÑу Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ (чтобы вы могли идентифицировать выÑтавленный Ñчёт). Она приÑоединÑетÑÑ Ðº запроÑу платежа.</translation>
</message>
<message>
<source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
@@ -3028,7 +3546,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation type="unfinished">Очищает вÑе Ð¿Ð¾Ð»Ñ Ñ„Ð¾Ñ€Ð¼Ñ‹.</translation>
+ <translation type="unfinished">ОчиÑтить вÑе Ð¿Ð¾Ð»Ñ Ñ„Ð¾Ñ€Ð¼Ñ‹.</translation>
</message>
<message>
<source>Clear</source>
@@ -3040,7 +3558,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>Show the selected request (does the same as double clicking an entry)</source>
- <translation type="unfinished">Показывает выбранный Ð·Ð°Ð¿Ñ€Ð¾Ñ (двойное нажатие на запиÑи делает то же Ñамое)</translation>
+ <translation type="unfinished">Показать выбранный Ð·Ð°Ð¿Ñ€Ð¾Ñ (двойное нажатие на запиÑи Ñделает то же Ñамое)</translation>
</message>
<message>
<source>Show</source>
@@ -3048,7 +3566,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>Remove the selected entries from the list</source>
- <translation type="unfinished">УдалÑет выбранные запиÑи из ÑпиÑка</translation>
+ <translation type="unfinished">Удалить выбранные запиÑи из ÑпиÑка</translation>
</message>
<message>
<source>Remove</source>
@@ -3059,6 +3577,22 @@ For more information on using this console, type %6.
<translation type="unfinished">Копировать &amp;URI</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Копировать адреÑ</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копировать &amp;метку</translation>
+ </message>
+ <message>
+ <source>Copy &amp;message</source>
+ <translation type="unfinished">Копировать &amp;Ñообщение</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Копировать Ñ&amp;умму</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">Ðевозможно разблокировать кошелёк.</translation>
</message>
@@ -3071,7 +3605,7 @@ For more information on using this console, type %6.
<name>ReceiveRequestDialog</name>
<message>
<source>Request payment to …</source>
- <translation type="unfinished">ЗапроÑить платёж на ...</translation>
+ <translation type="unfinished">ЗапроÑить платёж на …</translation>
</message>
<message>
<source>Address:</source>
@@ -3102,8 +3636,16 @@ For more information on using this console, type %6.
<translation type="unfinished">Копировать &amp;адреÑ</translation>
</message>
<message>
+ <source>&amp;Verify</source>
+ <translation type="unfinished">&amp;Проверить</translation>
+ </message>
+ <message>
+ <source>Verify this address on e.g. a hardware wallet screen</source>
+ <translation type="unfinished">Проверьте Ð°Ð´Ñ€ÐµÑ Ð½Ð°, к примеру, Ñкране аппаратного кошелька</translation>
+ </message>
+ <message>
<source>&amp;Save Image…</source>
- <translation type="unfinished">&amp;Сохранить изображение...</translation>
+ <translation type="unfinished">&amp;Сохранить изображение…</translation>
</message>
<message>
<source>Payment information</source>
@@ -3189,7 +3731,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
- <translation type="unfinished">ЕÑли Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ñдачи пуÑтой или неверный, Ñдача будет отправлена на вновь Ñгенерированный адреÑ.</translation>
+ <translation type="unfinished">ЕÑли Ñто выбрано, но Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ñдачи пуÑтой или неверный, Ñдача будет отправлена на новый Ñгенерированный адреÑ.</translation>
</message>
<message>
<source>Custom change address</source>
@@ -3233,11 +3775,11 @@ For more information on using this console, type %6.
</message>
<message>
<source>Clear all fields of the form.</source>
- <translation type="unfinished">Очищает вÑе Ð¿Ð¾Ð»Ñ Ñ„Ð¾Ñ€Ð¼Ñ‹.</translation>
+ <translation type="unfinished">ОчиÑтить вÑе Ð¿Ð¾Ð»Ñ Ñ„Ð¾Ñ€Ð¼Ñ‹.</translation>
</message>
<message>
<source>Inputs…</source>
- <translation type="unfinished">Входы...</translation>
+ <translation type="unfinished">Входы…</translation>
</message>
<message>
<source>Dust:</source>
@@ -3245,7 +3787,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>Choose…</source>
- <translation type="unfinished">Выбрать...</translation>
+ <translation type="unfinished">Выбрать…</translation>
</message>
<message>
<source>Hide transaction fee settings</source>
@@ -3257,11 +3799,11 @@ For more information on using this console, type %6.
Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
<translation type="unfinished">Укажите пользовательÑкую комиÑÑию за КБ (1000 байт) виртуального размера транзакции.
-Примечание: так как комиÑÑÐ¸Ñ Ñ€Ð°ÑÑчитываетÑÑ Ð¿Ñ€Ð¾Ð¿Ð¾Ñ€Ñ†Ð¸Ð¾Ð½Ð°Ð»ÑŒÐ½Ð¾ размеру в байтах, комиÑÑÐ¸Ñ Â«100 Ñатоши за ВКБ» Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ð¸ размером 500 виртуальных байт (половина 1 ВКБ) приведет к Ñбору в размере вÑего 50 Ñатоши.</translation>
+Примечание: комиÑÑÐ¸Ñ Ñ€Ð°ÑÑчитываетÑÑ Ð¿Ñ€Ð¾Ð¿Ð¾Ñ€Ñ†Ð¸Ð¾Ð½Ð°Ð»ÑŒÐ½Ð¾ размеру в байтах. Так при комиÑÑии "100 Ñатоши за kvB (виртуальный КБ)" Ð´Ð»Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ð¸ размером 500 виртуальных байт (половина 1 kvB) комиÑÑÐ¸Ñ Ð±ÑƒÐ´ÐµÑ‚ вÑего 50 Ñатоши.</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">Когда объём транзакций меньше, чем проÑтранÑтво в блоках, майнеры и ретранÑлирующие узлы могут уÑтанавливать минимальную комиÑÑию. Платить только Ñту минимальную комиÑÑию вполне допуÑтимо, но примите во внимание, что ваша Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ никогда не подтвердитьÑÑ, еÑли впоÑледÑтвии транзакций окажетÑÑ Ð±Ð¾Ð»ÑŒÑˆÐµ, чем может обработать Ñеть.</translation>
+ <translation type="unfinished">Когда объём транзакций меньше, чем проÑтранÑтво в блоках, майнеры и ретранÑлирующие узлы могут уÑтанавливать минимальную комиÑÑию. Платить только Ñту минимальную комиÑÑию вполне допуÑтимо, но примите во внимание, что ваша Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ никогда не подтвердитьÑÑ, еÑли транзакций окажетÑÑ Ð±Ð¾Ð»ÑŒÑˆÐµ, чем может обработать Ñеть.</translation>
</message>
<message>
<source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
@@ -3269,11 +3811,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks…)</source>
- <translation type="unfinished">(Ð£Ð¼Ð½Ð°Ñ ÐºÐ¾Ð¼Ð¸ÑÑÐ¸Ñ Ð¿Ð¾ÐºÐ° не инициализирована. Обычно Ð´Ð»Ñ Ñтого требуетÑÑ Ð½ÐµÑколько блоков...)</translation>
+ <translation type="unfinished">(Ð£Ð¼Ð½Ð°Ñ ÐºÐ¾Ð¼Ð¸ÑÑÐ¸Ñ Ð¿Ð¾ÐºÐ° не инициализирована. Обычно Ð´Ð»Ñ Ñтого требуетÑÑ Ð½ÐµÑколько блоков…)</translation>
</message>
<message>
<source>Confirmation time target:</source>
- <translation type="unfinished">Целевое Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ</translation>
+ <translation type="unfinished">Целевое Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ:</translation>
</message>
<message>
<source>Enable Replace-By-Fee</source>
@@ -3281,7 +3823,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
- <translation type="unfinished">С помощью Replace-By-Fee (BIP-125) вы можете увеличить комиÑÑию поÑле отправки транзакции. ЕÑли Ñта Ð¾Ð¿Ñ†Ð¸Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°, Ñ€ÐµÐºÐ¾Ð¼ÐµÐ½Ð´ÑƒÐµÐ¼Ð°Ñ ÐºÐ¾Ð¼Ð¸ÑÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ увеличитьÑÑ, чтобы компенÑировать риÑк задержки транзакции.</translation>
+ <translation type="unfinished">С помощью Replace-By-Fee (BIP-125) вы можете увеличить комиÑÑию поÑле отправки транзакции. ЕÑли вы выключите Ñту опцию, рекомендуетÑÑ ÑƒÐ²ÐµÐ»Ð¸Ñ‡Ð¸Ñ‚ÑŒ комиÑÑию перед отправкой, чтобы Ñнизить риÑк задержки транзакции.</translation>
</message>
<message>
<source>Clear &amp;All</source>
@@ -3293,7 +3835,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Confirm the send action</source>
- <translation type="unfinished">Подтвердите отправку</translation>
+ <translation type="unfinished">Подтвердить отправку</translation>
</message>
<message>
<source>S&amp;end</source>
@@ -3313,7 +3855,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Copy after fee</source>
- <translation type="unfinished">Копировать поÑле комиÑÑии</translation>
+ <translation type="unfinished">Копировать Ñумму поÑле комиÑÑии</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -3332,6 +3874,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">%1 (%2 блоков)</translation>
</message>
<message>
+ <source>Sign on device</source>
+ <extracomment>"device" usually means a hardware wallet.</extracomment>
+ <translation type="unfinished">Подтвердите на уÑтройÑтве</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">Сначала подключите ваш аппаратный кошелёк.</translation>
+ </message>
+ <message>
+ <source>Set external signer script path in Options -&gt; Wallet</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Укажите внешний Ñкрипт подпиÑи в ÐаÑтройки -&gt; Кошелек</translation>
+ </message>
+ <message>
<source>Cr&amp;eate Unsigned</source>
<translation type="unfinished">Создать &amp;без подпиÑи</translation>
</message>
@@ -3341,23 +3897,33 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source> from wallet '%1'</source>
- <translation type="unfinished">Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ° '%1'</translation>
+ <translation type="unfinished">Ñ ÐºÐ¾ÑˆÐµÐ»ÑŒÐºÐ° "%1"</translation>
</message>
<message>
<source>%1 to '%2'</source>
- <translation type="unfinished">%1 на '%2'</translation>
+ <translation type="unfinished">%1 на "%2"</translation>
</message>
<message>
<source>%1 to %2</source>
- <translation type="unfinished">С %1 на %2</translation>
+ <translation type="unfinished">%1 на %2</translation>
</message>
<message>
<source>To review recipient list click "Show Details…"</source>
- <translation type="unfinished">Чтобы проÑмотреть ÑпиÑок получателей, нажмите «Показать подробноÑти...»</translation>
+ <translation type="unfinished">Чтобы проÑмотреть ÑпиÑок получателей, нажмите "Показать подробноÑти…"</translation>
</message>
<message>
<source>Sign failed</source>
- <translation type="unfinished">ПодпиÑание не удалоÑÑŒ.</translation>
+ <translation type="unfinished">Ðе удалоÑÑŒ подпиÑать</translation>
+ </message>
+ <message>
+ <source>External signer not found</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Внешний Ñкрипт подпиÑи не найден</translation>
+ </message>
+ <message>
+ <source>External signer failure</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Внешний Ñкрипта подпиÑи вернул ошибку</translation>
</message>
<message>
<source>Save Transaction Data</source>
@@ -3373,22 +3939,36 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">PSBT Ñохранена</translation>
</message>
<message>
+ <source>External balance:</source>
+ <translation type="unfinished">Внешний баланÑ:</translation>
+ </message>
+ <message>
<source>or</source>
<translation type="unfinished">или</translation>
</message>
<message>
<source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
- <translation type="unfinished">Ð’Ñ‹ можете увеличить комиÑÑию позже (указан Replace-By-Fee, BIP-125).</translation>
+ <translation type="unfinished">Ð’Ñ‹ можете увеличить комиÑÑию позже (иÑпользуетÑÑ Replace-By-Fee, BIP-125).</translation>
</message>
<message>
<source>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>
<extracomment>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.</extracomment>
- <translation type="unfinished">ПожалуйÑта, ещё раз проÑмотрите черновик вашей транзакции. Будет Ñоздана чаÑтично подпиÑÐ°Ð½Ð½Ð°Ñ Ð±Ð¸Ñ‚ÐºÐ¾Ð¸Ð½-Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ (PSBT), которую можно Ñохранить или Ñкопировать, поÑле чего подпиÑать, например, офлайновым кошельком %1 или PSBT-ÑовмеÑтимым аппаратным кошельком.</translation>
+ <translation type="unfinished">ПожалуйÑта, проверьте черновик вашей транзакции. Будет Ñоздана чаÑтично подпиÑÐ°Ð½Ð½Ð°Ñ Ð±Ð¸Ñ‚ÐºÐ¾Ð¸Ð½-Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ (PSBT), которую можно Ñохранить или Ñкопировать, поÑле чего подпиÑать, например, офлайновым кошельком %1 или PSBT-ÑовмеÑтимым аппаратным кошельком.</translation>
+ </message>
+ <message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Ð’Ñ‹ хотите Ñоздать Ñту транзакцию?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">ПожалуйÑта, проверьте вашу транзакцию. Ð’Ñ‹ можете Ñоздать и отправить Ñту транзакцию, либо Ñоздать чаÑтично подпиÑанную биткоин-транзакцию (PSBT), которую можно Ñохранить или Ñкопировать, поÑле чего подпиÑать, например, офлайновым кошельком %1 или PSBT-ÑовмеÑтимым аппаратным кошельком.</translation>
</message>
<message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
- <translation type="unfinished">ПожалуйÑта, ещё раз проÑмотрите вашу транзакцию.</translation>
+ <translation type="unfinished">ПожалуйÑта, проверьте вашу транзакцию.</translation>
</message>
<message>
<source>Transaction fee</source>
@@ -3396,7 +3976,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
- <translation type="unfinished">Ðе указан Replace-By-Fee, BIP-125.</translation>
+ <translation type="unfinished">Ðе иÑпользуетÑÑ Replace-By-Fee, BIP-125.</translation>
</message>
<message>
<source>Total Amount</source>
@@ -3404,11 +3984,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Confirm send coins</source>
- <translation type="unfinished">Подтвердите отправку монет</translation>
+ <translation type="unfinished">Подтвердить отправку монет</translation>
</message>
<message>
<source>Watch-only balance:</source>
- <translation type="unfinished">Ðаблюдаемый баланÑ:</translation>
+ <translation type="unfinished">Ð‘Ð°Ð»Ð°Ð½Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра:</translation>
</message>
<message>
<source>The recipient address is not valid. Please recheck.</source>
@@ -3436,27 +4016,23 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation type="unfinished">КомиÑÑÐ¸Ñ Ð±Ð¾Ð»ÐµÐµ чем в %1 ÑчитаетÑÑ Ð°Ð±Ñурдно выÑокой.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">ИÑтекло Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа платежа</translation>
+ <translation type="unfinished">КомиÑÑÐ¸Ñ Ð±Ð¾Ð»ÐµÐµ %1 ÑчитаетÑÑ Ð°Ð±Ñурдно выÑокой.</translation>
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>Подтверждение ожидаетÑÑ Ñ‡ÐµÑ€ÐµÐ· %n блок.</numerusform>
+ <numerusform>Подтверждение ожидаетÑÑ Ñ‡ÐµÑ€ÐµÐ· %n блока.</numerusform>
+ <numerusform>Подтверждение ожидаетÑÑ Ñ‡ÐµÑ€ÐµÐ· %n блоков.</numerusform>
</translation>
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
- <translation type="unfinished">Предупреждение: неверный биткоин-адреÑ</translation>
+ <translation type="unfinished">Внимание: неверный биткоин-адреÑ</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
- <translation type="unfinished">Предупреждение: неизвеÑтный Ð°Ð´Ñ€ÐµÑ Ñдачи</translation>
+ <translation type="unfinished">Внимание: неизвеÑтный Ð°Ð´Ñ€ÐµÑ Ñдачи</translation>
</message>
<message>
<source>Confirm custom change address</source>
@@ -3464,7 +4040,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>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>
- <translation type="unfinished">Выбранный вами Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ñдачи не принадлежит Ñтому кошельку. ЧаÑÑ‚ÑŒ или вÑе ÑредÑтва в вашем кошельке могут быть отправлены на Ñтот адреÑ. Ð’Ñ‹ уверены?</translation>
+ <translation type="unfinished">Выбранный вами Ð°Ð´Ñ€ÐµÑ Ð´Ð»Ñ Ñдачи не принадлежит Ñтому кошельку. ЧаÑÑ‚ÑŒ ÑредÑтв, а то и вÑÑ‘ Ñодержимое вашего кошелька будет отправлено на Ñтот адреÑ. Ð’Ñ‹ уверены в Ñвоих дейÑтвиÑÑ…?</translation>
</message>
<message>
<source>(no label)</source>
@@ -3507,7 +4083,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>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>
- <translation type="unfinished">КомиÑÑÐ¸Ñ Ð±ÑƒÐ´ÐµÑ‚ вычтена из отправлÑемой Ñуммы. Получателю придёт меньше биткоинов, чем вы ввели в поле «Сумма». ЕÑли выбрано неÑколько получателей, комиÑÑÐ¸Ñ Ñ€Ð°ÑпределÑетÑÑ Ð¿Ð¾Ñ€Ð¾Ð²Ð½Ñƒ.</translation>
+ <translation type="unfinished">КомиÑÑÐ¸Ñ Ð±ÑƒÐ´ÐµÑ‚ вычтена из отправлÑемой Ñуммы. Получателю придёт меньше биткоинов, чем вы ввели в поле "Сумма". ЕÑли выбрано неÑколько получателей, комиÑÑÐ¸Ñ Ñ€Ð°ÑпределитÑÑ Ð¿Ð¾Ñ€Ð¾Ð²Ð½Ñƒ.</translation>
</message>
<message>
<source>S&amp;ubtract fee from amount</source>
@@ -3522,28 +4098,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">Сообщение:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Это непроверенный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° оплату.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Это проверенный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° оплату.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Введите метку Ð´Ð»Ñ Ñтого адреÑа, чтобы добавить его в ÑпиÑок иÑпользованных адреÑов</translation>
</message>
<message>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
- <translation type="unfinished">Сообщение, которое было прикреплено к URI и которое будет Ñохранено вмеÑте Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸ÐµÐ¹ Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ ÑведениÑ. Обратите внимание: Ñообщение не будет отправлено через Ñеть биткоина.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Отправить на:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Примечание:</translation>
+ <translation type="unfinished">Сообщение, которое было прикреплено к URI. Оно будет Ñохранено вмеÑте Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸ÐµÐ¹ Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ удобÑтва. Обратите внимание: Ñто Ñообщение не будет отправлено в Ñеть Bitcoin.</translation>
</message>
</context>
<context>
@@ -3617,7 +4177,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation type="unfinished">Введите ниже Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÐµÐ»Ñ, Ñообщение (убедитеÑÑŒ, что переводы Ñтрок, пробелы, знаки табулÑции и Ñ‚. п. Ñкопированы в точноÑти) и подпиÑÑŒ, чтобы проверить Ñообщение. УбедитеÑÑŒ, что вы не придаёте Ñообщению большего ÑмыÑла, чем оно на Ñамом деле неÑÑ‘Ñ‚, чтобы не Ñтать жертвой атаки "человек поÑередине". Обратите внимание, что подпиÑÑŒ доказывает лишь то, что подпиÑавший может получать биткоины на Ñтот адреÑ, но никак не то, что он отправил какую-либо транзакцию!</translation>
+ <translation type="unfinished">Введите ниже Ð°Ð´Ñ€ÐµÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚ÐµÐ»Ñ, Ñообщение (убедитеÑÑŒ, что переводы Ñтрок, пробелы, знаки табулÑции и Ñ‚.п. Ñкопированы в точноÑти) и подпиÑÑŒ, чтобы проверить Ñообщение. Ðе придавайте Ñообщению большего ÑмыÑла, чем в нём ÑодержитÑÑ, чтобы не Ñтать жертвой атаки "человек поÑередине". Обратите внимание, что подпиÑÑŒ доказывает лишь то, что подпиÑавший может получать биткоины на Ñтот адреÑ, но никак не то, что он отправил какую-либо транзакцию!</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
@@ -3665,11 +4225,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>No error</source>
- <translation type="unfinished">Ðет ошибок</translation>
+ <translation type="unfinished">Без ошибок</translation>
</message>
<message>
<source>Private key for the entered address is not available.</source>
- <translation type="unfinished">ÐедоÑтупен Ñекретный ключ Ð´Ð»Ñ Ð²Ð²ÐµÐ´Ñ‘Ð½Ð½Ð¾Ð³Ð¾ адреÑа.</translation>
+ <translation type="unfinished">Приватный ключ Ð´Ð»Ñ Ð²Ð²ÐµÐ´Ñ‘Ð½Ð½Ð¾Ð³Ð¾ адреÑа недоÑтупен.</translation>
</message>
<message>
<source>Message signing failed.</source>
@@ -3689,7 +4249,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>The signature did not match the message digest.</source>
- <translation type="unfinished">ПодпиÑÑŒ не ÑоответÑтвует отпечатку ÑообщениÑ.</translation>
+ <translation type="unfinished">ПодпиÑÑŒ не ÑоответÑтвует Ñ…Ñшу ÑообщениÑ.</translation>
</message>
<message>
<source>Message verification failed.</source>
@@ -3706,7 +4266,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>(press q to shutdown and continue later)</source>
<translation type="unfinished">(нажмите q, чтобы завершить работу и продолжить позже)</translation>
</message>
- </context>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">нажмите q Ð´Ð»Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
<message>
@@ -3718,30 +4282,32 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">конфликтует Ñ Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸ÐµÐ¹ Ñ %1 подтверждениÑми</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0 / не подтверждено, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">в пуле памÑти</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/нет подтверждений, в пуле памÑти</translation>
</message>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">не в пуле памÑти</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/нет подтверждений, не в пуле памÑти</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">отброшена</translation>
</message>
<message>
<source>%1/unconfirmed</source>
- <translation type="unfinished">%1 / не подтверждено</translation>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
+ <translation type="unfinished">%1/нет подтверждений</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 подтверждений</translation>
</message>
<message>
@@ -3762,7 +4328,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>From</source>
- <translation type="unfinished">От</translation>
+ <translation type="unfinished">От кого</translation>
</message>
<message>
<source>unknown</source>
@@ -3791,9 +4357,9 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
- <numerusform />
- <numerusform />
+ <numerusform>Ñозреет через %n блок</numerusform>
+ <numerusform>Ñозреет через %n блока</numerusform>
+ <numerusform>Ñозреет через %n блоков</numerusform>
</translation>
</message>
<message>
@@ -3818,7 +4384,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Net amount</source>
- <translation type="unfinished">Сумма нетто</translation>
+ <translation type="unfinished">ЧиÑÑ‚Ð°Ñ Ñумма</translation>
</message>
<message>
<source>Message</source>
@@ -3932,7 +4498,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Generated but not accepted</source>
- <translation type="unfinished">Сгенерирована, но не принÑта</translation>
+ <translation type="unfinished">Сгенерирован, но не принÑÑ‚</translation>
</message>
<message>
<source>Received with</source>
@@ -3952,7 +4518,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Mined</source>
- <translation type="unfinished">Добыта</translation>
+ <translation type="unfinished">Добыто</translation>
</message>
<message>
<source>watch-only</source>
@@ -4003,19 +4569,19 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>This week</source>
- <translation type="unfinished">Эта неделÑ</translation>
+ <translation type="unfinished">Ðа Ñтой неделе</translation>
</message>
<message>
<source>This month</source>
- <translation type="unfinished">Этот меÑÑц</translation>
+ <translation type="unfinished">Ð’ Ñтом меÑÑце</translation>
</message>
<message>
<source>Last month</source>
- <translation type="unfinished">ПоÑледний меÑÑц</translation>
+ <translation type="unfinished">Ð’ прошлом меÑÑце</translation>
</message>
<message>
<source>This year</source>
- <translation type="unfinished">Этот год</translation>
+ <translation type="unfinished">Ð’ Ñтом году</translation>
</message>
<message>
<source>Received with</source>
@@ -4031,7 +4597,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Mined</source>
- <translation type="unfinished">Добыта</translation>
+ <translation type="unfinished">Добыто</translation>
</message>
<message>
<source>Other</source>
@@ -4039,17 +4605,62 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Enter address, transaction id, or label to search</source>
- <translation type="unfinished">Введите адреÑ, идентификатор транзакции или метку Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка</translation>
+ <translation type="unfinished">Введите адреÑ, идентификатор транзакции, или метку Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка</translation>
</message>
<message>
<source>Min amount</source>
- <translation type="unfinished">Мин. Ñумма</translation>
+ <translation type="unfinished">ÐœÐ¸Ð½Ð¸Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ Ñумма</translation>
</message>
<message>
<source>Range…</source>
<translation type="unfinished">Диапазон...</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Копировать адреÑ</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копировать &amp;метку</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Копировать Ñ&amp;умму</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">Копировать ID &amp;транзакции</translation>
+ </message>
+ <message>
+ <source>Copy &amp;raw transaction</source>
+ <translation type="unfinished">Копировать &amp;иÑходный код транзакции</translation>
+ </message>
+ <message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">Копировать &amp;вÑе подробноÑти транзакции</translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">&amp;Показать подробноÑти транзакции</translation>
+ </message>
+ <message>
+ <source>Increase transaction &amp;fee</source>
+ <translation type="unfinished">Увеличить комиÑÑию</translation>
+ </message>
+ <message>
+ <source>A&amp;bandon transaction</source>
+ <translation type="unfinished">&amp;Отказ от транзакции</translation>
+ </message>
+ <message>
+ <source>&amp;Edit address label</source>
+ <translation type="unfinished">&amp;Изменить метку адреÑа</translation>
+ </message>
+ <message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Показать в %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">ЭкÑпортировать иÑторию транзакций</translation>
</message>
@@ -4084,7 +4695,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>ID</source>
- <translation type="unfinished">Идентификатр</translation>
+ <translation type="unfinished">Идентификатор</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -4108,7 +4719,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>to</source>
- <translation type="unfinished">длÑ</translation>
+ <translation type="unfinished">до</translation>
</message>
</context>
<context>
@@ -4175,7 +4786,7 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<source>Increase:</source>
- <translation type="unfinished">Увеличение:</translation>
+ <translation type="unfinished">Увеличить на:</translation>
</message>
<message>
<source>New fee:</source>
@@ -4183,15 +4794,15 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<source>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>
- <translation type="unfinished">Внимание: комиÑÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть увеличена путём ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð²Ñ‹Ð²Ð¾Ð´Ð¾Ð² Ð´Ð»Ñ Ñдачи или Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð¾Ð² (по необходимоÑти). Может быть добавлен новый вывод Ð´Ð»Ñ Ñдачи, еÑли он не ÑущеÑтвует. Эти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ привеÑти к ухудшению вашей конфиденциальноÑти.Ñ‘</translation>
+ <translation type="unfinished">Внимание: комиÑÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть увеличена путём ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð²Ñ‹Ñ…Ð¾Ð´Ð¾Ð² Ð´Ð»Ñ Ñдачи или Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ñ…Ð¾Ð´Ð¾Ð² (по необходимоÑти). Может быть добавлен новый вывод Ð´Ð»Ñ Ñдачи, еÑли он не ÑущеÑтвует. Эти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ привеÑти к ухудшению вашей конфиденциальноÑти.</translation>
</message>
<message>
<source>Confirm fee bump</source>
- <translation type="unfinished">Подтвердите увеличение комиÑÑии</translation>
+ <translation type="unfinished">Подтвердить увеличение комиÑÑии</translation>
</message>
<message>
<source>Can't draft transaction.</source>
- <translation type="unfinished">Ðевозможно подготовить черновик транзакции.</translation>
+ <translation type="unfinished">Ðе удалоÑÑŒ подготовить черновик транзакции.</translation>
</message>
<message>
<source>PSBT copied</source>
@@ -4206,6 +4817,10 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished">Ðе удалоÑÑŒ отправить транзакцию</translation>
</message>
<message>
+ <source>Can't display address</source>
+ <translation type="unfinished">Ðе удалоÑÑŒ отобразить адреÑ</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">кошелёк по умолчанию</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sc.ts b/src/qt/locale/bitcoin_sc.ts
index 1527753c8e..69bcdfb2d7 100644
--- a/src/qt/locale/bitcoin_sc.ts
+++ b/src/qt/locale/bitcoin_sc.ts
@@ -116,6 +116,24 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_si.ts b/src/qt/locale/bitcoin_si.ts
index c9367ad9d2..b6d95c0b6c 100644
--- a/src/qt/locale/bitcoin_si.ts
+++ b/src/qt/locale/bitcoin_si.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">ලිපිනය හ෠ලේබලය සංස්කරණය කිරීමට දකුණු මූසික බොත්තම ක්ලික් කරන්න</translation>
+ <translation type="unfinished">ලිපිනය හ෠නම්පත සංà·à·à¶°à¶±à¶ºà¶§ දකුණු බොත්තම ඔබන්න</translation>
</message>
<message>
<source>Create a new address</source>
@@ -15,11 +15,11 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation type="unfinished">දà·à¶±à¶§ තà·à¶»à·à¶œà·™à¶± ඇති ලිපිනය පද්ධති පසුරු පුවරුවට (clipboard) පිටපත් කරන්න</translation>
+ <translation type="unfinished">තà·à¶»à·à¶œà·™à¶± ඇති ලිපිනය පද්ධතියේ පසුරු පුවරුවට පිටපත් කරන්න</translation>
</message>
<message>
<source>&amp;Copy</source>
- <translation type="unfinished">&amp;පිටපත් කරන්න</translation>
+ <translation type="unfinished">&amp;පිටපත්</translation>
</message>
<message>
<source>C&amp;lose</source>
@@ -27,15 +27,23 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished">දà·à¶±à¶§ තà·à¶»à·à¶œà¶­à·Š ලිපිනය ලà·à¶ºà·’ස්තුවෙන් ඉවත් කරන්න</translation>
+ <translation type="unfinished">තේරූ ලිපිනය ලේඛනයෙන් මකන්න</translation>
</message>
<message>
<source>Enter address or label to search</source>
- <translation type="unfinished">සෙවීමට ලිපිනය හ෠ලේබලය ඇතුළත් කරන්න</translation>
+ <translation type="unfinished">සෙවීමට ලිපිනය හ෠නම්පත යොදන්න</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">වත්මන් පටියෙයි දත්ත ගොනුවකට නිර්යà·à¶­ කරන්න</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">&amp;නිර්යà·à¶­ කරන්න</translation>
+ <translation type="unfinished">&amp;නිර්යà·à¶­à¶º</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">&amp;මකන්න</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
@@ -47,7 +55,7 @@
</message>
<message>
<source>C&amp;hoose</source>
- <translation type="unfinished">තà·à¶»à¶±à·Šà¶±</translation>
+ <translation type="unfinished">තà·&amp;රන්න</translation>
</message>
<message>
<source>Sending addresses</source>
@@ -59,11 +67,15 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation type="unfinished">මේව෠ඔබගේ ගෙවීම් යà·à·€à·“ම සඳහ෠වන බිට්කොයින් ලිපින වේ. කà·à·ƒà·’ යà·à·€à·“මට පෙර සෑම විටම මුදල සහ ලà·à¶¶à·“මේ ලිපිනය පරීක්ෂ෠කරන්න.</translation>
+ <translation type="unfinished">මේ ඔබගේ ගෙවීම් යà·à·€à·“ම සඳහ෠වන බිට්කොයින් ලිපින වේ. කà·à·ƒà·’ යà·à·€à·“මට පෙර සෑම විටම මුදල සහ ලà·à¶¶à·“මේ ලිපිනය පරීක්â€à·‚෠කරන්න.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation type="unfinished">&amp;ලිපිනය පිටපත්</translation>
+ <translation type="unfinished">&amp;ලිපිනයෙහි පිටපතක්</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">නම්පතෙහි &amp;පිටපතක්</translation>
</message>
<message>
<source>&amp;Edit</source>
@@ -72,7 +84,7 @@
<message>
<source>Comma separated file</source>
<extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
- <translation type="unfinished">අල්පවිරà·à¶¸ වලින් වෙන්වූ ගොනුව</translation>
+ <translation type="unfinished">අල්පවිරà·à¶¸ යෙදූ ගොනුව</translation>
</message>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
@@ -81,14 +93,14 @@
</message>
<message>
<source>Exporting Failed</source>
- <translation type="unfinished">නිර්යà·à¶­ වීමට අසමත් විය</translation>
+ <translation type="unfinished">නිර්යà·à¶­à¶ºà¶§ අසමත් විය</translation>
</message>
</context>
<context>
<name>AddressTableModel</name>
<message>
<source>Label</source>
- <translation type="unfinished">ලේබලය</translation>
+ <translation type="unfinished">නම්පත</translation>
</message>
<message>
<source>Address</source>
@@ -96,7 +108,7 @@
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ලේබලයක් නà·à¶­)</translation>
+ <translation type="unfinished">(නම්පතක් නà·à¶­)</translation>
</message>
</context>
<context>
@@ -123,7 +135,7 @@
</message>
<message>
<source>Encrypt wallet</source>
- <translation type="unfinished">පසුම්බිය සංකේතනය කරන්න</translation>
+ <translation type="unfinished">පසුම්බිය සංකේතනය</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
@@ -151,7 +163,7 @@
</message>
<message>
<source>Wallet encrypted</source>
- <translation type="unfinished">පසුම්බිය සංකේතනය කර ඇත</translation>
+ <translation type="unfinished">පසුම්බිය සංකේතිතයි</translation>
</message>
<message>
<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>
@@ -171,11 +183,11 @@
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation type="unfinished">ඔබේ මුදල් පසුම්බිය සංකේතනය කිරීමට ආසන්නයි.</translation>
+ <translation type="unfinished">පසුම්බිය සංකේතනය කිරීමට ආසන්නයි.</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation type="unfinished">ඔබගේ මුදල් පසුම්බිය දà·à¶±à·Š සංකේතනය කර ඇත.</translation>
+ <translation type="unfinished">ඔබගේ මුදල් පසුම්බිය දà·à¶±à·Š සංකේතිතයි.</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
@@ -183,7 +195,7 @@
</message>
<message>
<source>Wallet encryption failed</source>
- <translation type="unfinished">පසුම්බි සංකේතනය අසà·à¶»à·Šà¶®à¶š විය</translation>
+ <translation type="unfinished">පසුම්බිය සංකේතනයට අසමත්!</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
@@ -325,7 +337,7 @@
</message>
<message>
<source>Quit application</source>
- <translation type="unfinished">යෙදුමෙන් පිටවන්න</translation>
+ <translation type="unfinished">යෙදුම වසන්න</translation>
</message>
<message>
<source>&amp;About %1</source>
@@ -333,7 +345,7 @@
</message>
<message>
<source>Show information about %1</source>
- <translation type="unfinished">%1 පිළිබඳව තෙà·à¶»à¶­à·”රු පෙන්වන්න</translation>
+ <translation type="unfinished">%1 ගà·à¶± තෙà·à¶»à¶­à·”රු පෙන්වන්න</translation>
</message>
<message>
<source>About &amp;Qt</source>
@@ -341,13 +353,17 @@
</message>
<message>
<source>Show information about Qt</source>
- <translation type="unfinished">කියුටී පිළිබඳව තෙà·à¶»à¶­à·”රු පෙන්වන්න</translation>
+ <translation type="unfinished">කියුටී ගà·à¶± තෙà·à¶»à¶­à·”රු පෙන්වන්න</translation>
</message>
<message>
<source>Create a new wallet</source>
<translation type="unfinished">නව පසුම්බියක් à·ƒà·à¶¯à¶±à·Šà¶±</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;හකුළන්න</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">පසුම්බිය:</translation>
</message>
@@ -358,7 +374,7 @@
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation type="unfinished">බිට්කෙà·à¶ºà·’න් ලිපිනයට කà·à·ƒà·’ යවන්න</translation>
+ <translation type="unfinished">බිට්කෙà·à¶ºà·’න් ලිපිනයකට කà·à·ƒà·’ යවන්න</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -378,7 +394,7 @@
</message>
<message>
<source>&amp;Backup Wallet…</source>
- <translation type="unfinished">&amp;පසුම්බිය උපස්ථකරන්න…</translation>
+ <translation type="unfinished">&amp;පසුම්බිය උපස්ථය…</translation>
</message>
<message>
<source>Close Wallet…</source>
@@ -406,7 +422,7 @@
</message>
<message>
<source>Syncing Headers (%1%)…</source>
- <translation type="unfinished">(%1%) à·à·“ර්ෂ සමමුහූර්ත වෙමින්…</translation>
+ <translation type="unfinished">(%1%) à·à·Šâ€à¶»à·“ර්ෂ සමමුහූර්ත වෙමින්…</translation>
</message>
<message>
<source>Synchronizing with network…</source>
@@ -432,6 +448,10 @@
<translation type="unfinished">තොරතුර</translation>
</message>
<message>
+ <source>Up to date</source>
+ <translation type="unfinished">යà·à·€à¶­à·Šà¶šà·à¶½à·“නයි</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation type="unfinished">&amp;යවන ලිපින</translation>
</message>
@@ -460,12 +480,22 @@
<translation type="unfinished">පෙරනිමි පසුම්බිය</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">පසුම්බියේ දත්ත</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">පසුම්බියේ නම</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;කවුළුව</translation>
</message>
<message>
<source>Zoom</source>
- <translation type="unfinished">විà·à·à¶½ කරන්න</translation>
+ <translation type="unfinished">විà·à·à¶½à¶±à¶º</translation>
</message>
<message>
<source>Main Window</source>
@@ -475,6 +505,14 @@
<source>%1 client</source>
<translation type="unfinished">%1 අනුග්â€à¶»à·à·„කය</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;සඟවන්න</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">පෙ&amp;න්වන්න</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -513,6 +551,12 @@
</translation>
</message>
<message>
+ <source>Amount: %1
+</source>
+ <translation type="unfinished">ගණන: %1
+</translation>
+ </message>
+ <message>
<source>Wallet: %1
</source>
<translation type="unfinished">පසුම්බිය: %1
@@ -525,6 +569,12 @@
</translation>
</message>
<message>
+ <source>Label: %1
+</source>
+ <translation type="unfinished">නම්පත: %1
+</translation>
+ </message>
+ <message>
<source>Address: %1
</source>
<translation type="unfinished">ලිපිනය: %1
@@ -575,7 +625,7 @@
</message>
<message>
<source>&amp;Copy address</source>
- <translation type="unfinished">&amp;ලිපිනය පිටපත්</translation>
+ <translation type="unfinished">&amp;ලිපිනයෙහි පිටපතක්</translation>
</message>
<message>
<source>Copy bytes</source>
@@ -591,7 +641,7 @@
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ලේබලයක් නà·à¶­)</translation>
+ <translation type="unfinished">(නම්පතක් නà·à¶­)</translation>
</message>
<message>
<source>(change)</source>
@@ -697,6 +747,27 @@
<translation type="unfinished">බිට්කෙà·à¶ºà·’න්</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -870,7 +941,7 @@
<message>
<source>&amp;Copy address</source>
<extracomment>Context menu action to copy the address of a peer.</extracomment>
- <translation type="unfinished">&amp;ලිපිනය පිටපත්</translation>
+ <translation type="unfinished">&amp;ලිපිනයෙහි පිටපතක්</translation>
</message>
<message>
<source>To</source>
@@ -885,7 +956,7 @@
<name>ReceiveCoinsDialog</name>
<message>
<source>&amp;Copy address</source>
- <translation type="unfinished">&amp;ලිපිනය පිටපත්</translation>
+ <translation type="unfinished">&amp;ලිපිනයෙහි පිටපතක්</translation>
</message>
</context>
<context>
@@ -907,7 +978,7 @@
</message>
<message>
<source>Label</source>
- <translation type="unfinished">ලේබලය</translation>
+ <translation type="unfinished">නම්පත</translation>
</message>
<message>
<source>Message</source>
@@ -915,7 +986,7 @@
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ලේබලයක් නà·à¶­)</translation>
+ <translation type="unfinished">(නම්පතක් නà·à¶­)</translation>
</message>
</context>
<context>
@@ -977,7 +1048,7 @@
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ලේබලයක් නà·à¶­)</translation>
+ <translation type="unfinished">(නම්පතක් නà·à¶­)</translation>
</message>
</context>
<context>
@@ -1060,7 +1131,7 @@
</message>
<message>
<source>Label</source>
- <translation type="unfinished">ලේබලය</translation>
+ <translation type="unfinished">නම්පත</translation>
</message>
<message>
<source>(n/a)</source>
@@ -1068,7 +1139,7 @@
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ලේබලයක් නà·à¶­)</translation>
+ <translation type="unfinished">(නම්පතක් නà·à¶­)</translation>
</message>
<message>
<source>Type of transaction.</source>
@@ -1103,7 +1174,7 @@
</message>
<message>
<source>&amp;Copy address</source>
- <translation type="unfinished">&amp;ලිපිනය පිටපත්</translation>
+ <translation type="unfinished">&amp;ලිපිනයෙහි පිටපතක්</translation>
</message>
<message>
<source>Copy transaction &amp;ID</source>
@@ -1112,7 +1183,7 @@
<message>
<source>Comma separated file</source>
<extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
- <translation type="unfinished">අල්පවිරà·à¶¸ වලින් වෙන්වූ ගොනුව</translation>
+ <translation type="unfinished">අල්පවිරà·à¶¸ යෙදූ ගොනුව</translation>
</message>
<message>
<source>Date</source>
@@ -1124,7 +1195,7 @@
</message>
<message>
<source>Label</source>
- <translation type="unfinished">ලේබලය</translation>
+ <translation type="unfinished">නම්පත</translation>
</message>
<message>
<source>Address</source>
@@ -1136,7 +1207,7 @@
</message>
<message>
<source>Exporting Failed</source>
- <translation type="unfinished">නිර්යà·à¶­ වීමට අසමත් විය</translation>
+ <translation type="unfinished">නිර්යà·à¶­à¶ºà¶§ අසමත් විය</translation>
</message>
<message>
<source>Exporting Successful</source>
@@ -1173,7 +1244,11 @@
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">&amp;නිර්යà·à¶­ කරන්න</translation>
+ <translation type="unfinished">&amp;නිර්යà·à¶­à¶º</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">වත්මන් පටියෙයි දත්ත ගොනුවකට නිර්යà·à¶­ කරන්න</translation>
</message>
<message>
<source>Backup Wallet</source>
diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts
index fb03b0beb6..65f339bf0c 100644
--- a/src/qt/locale/bitcoin_sk.ts
+++ b/src/qt/locale/bitcoin_sk.ts
@@ -264,6 +264,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Chcete vrátiÅ¥ nastavenia na predvolené hodnoty alebo ukonÄiÅ¥ bez vykonania zmien?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Nastala kritická chyba. Skontrolujte, že je možné zapisovať do súboru nastavení alebo skúste spustiť s parametrom -nosettings.</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Chyba: Zadaný adresár pre dáta „%1“ neexistuje.</translation>
</message>
@@ -393,6 +403,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Súbor nastavení nemohol byÅ¥ preÄítaný</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Súbor nastavení nemohol byť zapísaný</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">Vývojári %s</translation>
</message>
@@ -425,6 +443,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nastala chyba pri Äítaní súboru %s! VÅ¡etkz kľúÄe sa preÄítali správne, ale dáta o transakcíách alebo záznamy v adresári môžu chýbaÅ¥ alebo byÅ¥ nesprávne.</translation>
</message>
<message>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Chyba pri Äítaní %s! TransakÄné údaje môžu chýbaÅ¥ alebo sú chybné. Znovu preÄítam peňaženku.</translation>
+ </message>
+ <message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
<translation type="unfinished">Chyba: Formát záznamu v súbore dumpu je nesprávny. Obdržaný "%s", oÄakávaný "format".</translation>
</message>
@@ -441,10 +463,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Chyba: Staršie peňaženky podporujú len adresy typu "legacy", "p2sh-segwit", a "bech32"</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Chyba: PoÄúvanie prichádzajúcich spojení zlyhalo (vrátená chyba je %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Odhad poplatku sa nepodaril. Fallbackfee je zakázaný. PoÄkajte niekoľko blokov alebo povoľte -fallbackfee.</translation>
</message>
@@ -457,6 +475,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Neplatná suma pre -maxtxfee=&lt;amount&gt;: '%s' (aby sa transakcia nezasekla, minimálny prenosový poplatok musí byť aspoň %s)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Chybný alebo poÅ¡kodený súbor peers.dat (%s). Ak si myslíte, že ide o chybu, prosím nahláste to na %s. Ako doÄasné rieÅ¡enie môžete súbor odsunúť (%s) z umiestnenia (premenovaÅ¥, presunúť, vymazaÅ¥), aby sa pri ÄalÅ¡om spustení vytvoril nový.</translation>
+ </message>
+ <message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
<translation type="unfinished">K dispozícii je viac ako jedna adresa onion. Použitie %s pre automaticky vytvorenú službu Tor.</translation>
</message>
@@ -497,6 +519,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Databáza blokov obsahuje blok, ktorý vyzerá byÅ¥ z budúcnosti. Toto môže byÅ¥ spôsobené nesprávnym systémovým Äasom vášho poÄítaÄa. Obnovujte databázu blokov len keÄ ste si istý, že systémový Äas je nastavený správne.</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">Databáza indexov blokov obsahuje 'txindex' staršieho typu. Pre uvoľnenie obsadeného miesta spustite s parametrom -reindex, inak môžete ignorovať túto chybu. Táto správa sa už nabudúce nezobrazí.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">Suma je príliš malá pre odoslanie transakcie</translation>
</message>
@@ -569,6 +595,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nedá preložiť -%s adresu: '%s'</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">Nie je možné zapnúť -forcednsseed keÄ je -dnsseed vypnuté.</translation>
+ </message>
+ <message>
<source>Cannot set -peerblockfilters without -blockfilterindex.</source>
<translation type="unfinished">Nepodarilo sa urÄiÅ¥ -peerblockfilters bez -blockfilterindex.</translation>
</message>
@@ -577,6 +607,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nie je možné zapísať do adresára ' %s'. Skontrolujte povolenia.</translation>
</message>
<message>
+ <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">Upgrade -txindex spustený predchádzajúcou verziou nemôže byÅ¥ dokonÄený. ReÅ¡tartujte s prechdádzajúcou verziou programu alebo spustite s parametrom -reindex.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">Požiadavka %s na poÄúvanie na porte %u. Tento port je považovaný za "zlý" preto je nepravdepodobné, že sa naň pripojí nejaký Bitcoin Core partner. Pozrite doc/p2p-bad-ports.md pre detaily a celý zoznam.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Nie je možné zadať špecifické spojenia a zároveň nechať addrman hľadať odchádzajúce spojenia.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Chyba pri naÄítaní %s: NaÄíta sa peňaženka s externým podpisovaním, ale podpora pre externé podpisovanie nebola zaÄlenená do programu</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Nepodarilo sa premenovať chybný súbor peers.dat. Prosím presuňte ho alebo vymažte a skúste znovu.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Nastavenie konfigurácie pre %s platí iba v sieti %s a v sekcii [%s].</translation>
</message>
@@ -653,10 +703,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Chyba pri Äítaní ÄalÅ¡ieho záznamu z databázy peňaženky</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Chyba pri vylepšení databáze reťzcov blokov</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Chyba: Nepodarilo sa vytvoriť kurzor do databázy</translation>
</message>
@@ -729,6 +775,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kontrola Äistoty pri inicializácií zlyhala. %s sa vypína.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Vstup nenájdený alebo už minutý</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">Nedostatok prostriedkov</translation>
</message>
@@ -785,12 +835,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">NaÄítavam peňaženku…</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Chýba suma</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">Chýbajú údaje pre odhad veľkosti transakcie</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Je potrebné zadať port s -whitebind: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Nie je špecifikovaný proxy server. Použite -proxy=&lt;ip&gt; alebo -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Nie sú dostupné žiadne adresy</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -801,10 +859,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Redukovanie nemôže byť nastavené na zápornú hodnotu.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Režim redukovania je nekompatibilný s -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Režim redukovania je nekompatibilný s -txindex.</translation>
</message>
@@ -905,6 +959,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Sumy transakcií nesmú byť záporné</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Výstupný index transakcie zmeny je mimo rozsahu</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">Transakcia má v transakÄnom zásobníku príliÅ¡ dlhý reÅ¥azec</translation>
</message>
@@ -913,6 +971,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transakcia musí mať aspoň jedného príjemcu</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Transakcia potrebuje adresu na zmenu, ale nemôžeme ju vygenerovať.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">Transakcia príliš veľká</translation>
</message>
@@ -941,6 +1003,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nepodarilo sa otvoriť %s pre zapisovanie</translation>
</message>
<message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">Nepodarilo sa preÄítaÅ¥ -maxuploadtarget: '%s'</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">Nepodarilo sa spustiť HTTP server. Pre viac detailov zobrazte debug log.</translation>
</message>
@@ -969,10 +1035,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nepodporovaná logovacia kategória %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Vylepšuje sa databáza neminutých výstupov (UTXO)</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Komentár u typu klienta (%s) obsahuje riskantné znaky.</translation>
</message>
@@ -1040,6 +1102,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Vytvoriť novú peňaženku</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Minimalizovať</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Peňaženka:</translation>
</message>
@@ -1229,6 +1295,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">NaÄítaÅ¥ sÄasti podpísanú Bitcoin transakciu</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">NaÄítaÅ¥ PSBT zo s&amp;chránky…</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">NaÄítaÅ¥ ÄiastoÄne podpísanú Bitcoin transakciu, ktorú ste skopírovali</translation>
</message>
@@ -1289,6 +1359,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nie je dostupná žiadna peňaženka</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Dáta peňaženky</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Názov peňaženky</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Okno</translation>
</message>
@@ -1304,6 +1384,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 klient</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Skryť</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">Z&amp;obraziť</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1504,6 +1592,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Kopírovať &amp;sumu</translation>
</message>
<message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Skopírovať &amp;ID transakcie a výstupný index</translation>
+ </message>
+ <message>
<source>L&amp;ock unspent</source>
<translation type="unfinished">U&amp;zamknúť neminuté</translation>
</message>
@@ -1592,6 +1684,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">Nemôžem zobraziť podpisovateľov</translation>
</message>
+ </context>
+<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">NaÄítaÅ¥ peňaženky</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">NaÄítavam peňaženky…</translation>
+ </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1793,13 +1898,29 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(z %1 GB potrebných)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 GB potrebných pre plný reťazec)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1847,10 +1968,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">KeÄže toto je prvé spustenie programu, môžete si vybraÅ¥, kam %1 bude ukladaÅ¥ vaÅ¡e údaje.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">HneÄ po stlaÄení OK, zaÄne %1 sÅ¥ahovaÅ¥ a spracovávaÅ¥ celý %4 blockchain (%2G B), zaÄínajúc najaktuálnejšími transakciami z roku %3, kedy bol %4 spustený.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Obmedziť veľkosť reťazca blokov na</translation>
</message>
@@ -1959,7 +2076,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Neznámy. Synchronizujú sa hlaviÄky (%1, %2%)…</translation>
</message>
-</context>
+ </context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -2043,14 +2160,44 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Obnovenie tohto nastavenia vyžaduje opätovné stiahnutie celého blockchainu.</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">Maximálna veľkosÅ¥ vyrovnávacej pamäte databázy. VäÄÅ¡ia pamäť môže urýchliÅ¥ synchronizáciu, ale pri ÄalÅ¡om používaní už nemá efekt. ZmenÅ¡enie vyrovnávacej pamäte zníži použitie pamäte. Nevyužitá pamäť mempool je zdieľaná pre túto vyrovnávaciu pamäť.</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Nastaví poÄet vlákien na overenie skriptov. Záporné hodnoty zodpovedajú poÄtu jadier procesora, ktoré chcete nechaÅ¥ voľné pre systém.</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = auto, &lt;0 = toľko jadier nechať voľných)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Toto umožňuje vám alebo nástroju tretej strany komunikovať s uzlom pomocou príkazov z príkazového riadka alebo JSON-RPC.</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">Povoliť server R&amp;PC</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">&amp;Peňaženka</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">NastaviÅ¥ predvolenie odpoÄítavania poplatku zo sumy.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Predvolene odpoÄítavaÅ¥ &amp;poplatok zo sumy</translation>
+ </message>
+ <message>
<source>Enable coin &amp;control features</source>
<translation type="unfinished">Povoliť možnosti &amp;kontroly mincí</translation>
</message>
@@ -2063,6 +2210,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Minúť nepotvrdený výdavok</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Povoliť ovládanie &amp;PSBT</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Zobrazenie ovládania PSBT.</translation>
+ </message>
+ <message>
<source>External Signer (e.g. hardware wallet)</source>
<translation type="unfinished">Externý podpisovateľ (napr. hardvérová peňaženka)</translation>
</message>
@@ -2159,6 +2316,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Zvoľte ako deliť bitcoin pri zobrazovaní pri platbách a užívateľskom rozhraní.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">URL tretích strán (napr. prehliadaÄ blokov), ktoré sa zobrazujú v záložke transakcií ako položky kontextového menu. %s v URL je nahradené hash-om transakcie. Viaceré URL sú oddelené zvislou Äiarou |.</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">URL &amp;transakcií tretích strán</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">Či zobrazovať možnosti kontroly mincí alebo nie.</translation>
</message>
@@ -2183,10 +2348,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">najbližší zodpovedajúci "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Voľby nastavené v tomto dialógovom okne sú prepísané príkazovým riadkom alebo konfiguraÄným súborom:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Zrušiť</translation>
</message>
@@ -2205,14 +2366,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Potvrdiť obnovenie možností</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Reštart klienta potrebný pre aktivovanie zmien.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Klient bude vypnutý, chcete pokraÄovaÅ¥?</translation>
</message>
<message>
@@ -2226,6 +2390,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">KonfiguraÄný súbor slúži k nastavovaniu užívateľsky pokroÄilých možností, ktoré majú prednosÅ¥ pred konfiguráciou z grafického rozhrania. Parametre z príkazového riadka vÅ¡ak majú pred konfiguraÄným súborom prednosÅ¥.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">PokraÄovaÅ¥</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">Zrušiť</translation>
</message>
@@ -2360,6 +2528,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Nepodarilo sa podpísať transakciu: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Nemôžem podpísať vstupy kým je peňaženka zamknutá.</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">Nie je možné podpísaÅ¥ žiadne ÄalÅ¡ie vstupy.</translation>
</message>
@@ -2433,6 +2605,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Transakcii stále chýbajú podpis(y).</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Ale nie je naÄítaná žiadna peňaženka.)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(Ale táto peňaženka nemôže podpisovať transakcie)</translation>
</message>
@@ -2689,6 +2865,10 @@ Ak ste dostali túto chybu mali by ste požiadaÅ¥ obchodníka o URI kompatibilnÃ
<translation type="unfinished">Zosynchronizované bloky</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Posledná transakcia</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">Mapovaný nezávislý - Autonómny Systém používaný na rozšírenie vzájomného výberu peerov.</translation>
</message>
@@ -2697,12 +2877,32 @@ Ak ste dostali túto chybu mali by ste požiadaÅ¥ obchodníka o URI kompatibilnÃ
<translation type="unfinished">Mapovaný AS</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Postupovanie adries tomuto partnerovi.</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Postupovanie adries</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Spracované adresy</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Obmedzené adresy</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Aplikácia</translation>
</message>
<message>
<source>Node window</source>
- <translation type="unfinished">Okno uzlov</translation>
+ <translation type="unfinished">Uzlové okno</translation>
</message>
<message>
<source>Current block height</source>
@@ -2905,6 +3105,11 @@ Ak ste dostali túto chybu mali by ste požiadaÅ¥ obchodníka o URI kompatibilnÃ
<translation type="unfinished">1 &amp;rok</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">&amp;Kopírovať IP/Masku siete</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">&amp;Zrušiť zákaz</translation>
</message>
@@ -3433,6 +3638,16 @@ Poznámka: KeÄže poplatok je poÄítaný za bajt, poplatok pri sadzbe "100 sat
<translation type="unfinished">PreÄítajte si prosím svoj návrh transakcie. Výsledkom bude ÄiastoÄne podpísaná bitcoinová transakcia (PSBT), ktorú môžete uložiÅ¥ alebo skopírovaÅ¥ a potom podpísaÅ¥ napr. cez offline peňaženku %1 alebo hardvérovú peňaženku kompatibilnú s PSBT.</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Chcete vytvoriť túto transakciu?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Skontrolujte prosím svoj návrh transakcie. Môžete vytvoriÅ¥ a odoslaÅ¥ túto transakciu alebo vytvoriÅ¥ ÄiastoÄne podpísanú bitcoinovú transakciu (PSBT), ktorú môžete uložiÅ¥ alebo skopírovaÅ¥ a potom podpísaÅ¥ napr. cez offline peňaženku %1 alebo hardvérovú peňaženku kompatibilnú s PSBT.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Prosím, skontrolujte Vašu transakciu.</translation>
@@ -3485,10 +3700,6 @@ Poznámka: KeÄže poplatok je poÄítaný za bajt, poplatok pri sadzbe "100 sat
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Poplatok vyšší ako %1 sa považuje za neprimerane vysoký.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Vypršala platnosť požiadavky na platbu.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3569,14 +3780,6 @@ Poznámka: KeÄže poplatok je poÄítaný za bajt, poplatok pri sadzbe "100 sat
<translation type="unfinished">Správa:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Toto je neoverená výzva k platbe.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Toto je overená výzva k platbe.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Vložte popis pre túto adresu aby sa uložila do zoznamu použitých adries</translation>
</message>
@@ -3584,14 +3787,6 @@ Poznámka: KeÄže poplatok je poÄítaný za bajt, poplatok pri sadzbe "100 sat
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Správa ktorá bola pripojená k bitcoin: URI a ktorá bude uložená s transakcou pre Vaše potreby. Poznámka: Táto správa nebude poslaná cez sieť Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Platba pre:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Poznámka:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3753,35 +3948,31 @@ Poznámka: KeÄže poplatok je poÄítaný za bajt, poplatok pri sadzbe "100 sat
<source>(press q to shutdown and continue later)</source>
<translation type="unfinished">(stlaÄte Q pre ukonÄenie a pokraÄovanie neskôr)</translation>
</message>
- </context>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">stlaÄte q pre ukonÄenie</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">koliduje s transakciou s %1 potvrdeniami</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/nepotvrdené, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">v transakÄnom zásobníku</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">nie je v transakÄnom zásobníku</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">zanechaná</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/nepotvrdené</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 potvrdení</translation>
</message>
<message>
@@ -4126,6 +4317,11 @@ Poznámka: KeÄže poplatok je poÄítaný za bajt, poplatok pri sadzbe "100 sat
<translation type="unfinished">&amp;Upraviť popis transakcie</translation>
</message>
<message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Zobraziť v %1</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Exportovať históriu transakcií</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sl.ts b/src/qt/locale/bitcoin_sl.ts
index bf7e3c4dd1..c9f9aab92b 100644
--- a/src/qt/locale/bitcoin_sl.ts
+++ b/src/qt/locale/bitcoin_sl.ts
@@ -242,22 +242,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<context>
<name>BitcoinApplication</name>
<message>
- <source>Runaway exception</source>
- <translation type="unfinished">Pobegla izjema</translation>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Datoteka z nastavitvami %1 je morda ovkarjena ali neveljavna.</translation>
</message>
- <message>
- <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <translation type="unfinished">PriÅ¡lo je do usodne napake. %1 ne more veÄ varno nadaljevati s tekom in se bo ustavil.</translation>
- </message>
- <message>
- <source>Internal error</source>
- <translation type="unfinished">Interna napaka</translation>
- </message>
- <message>
- <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <translation type="unfinished">PriÅ¡lo je do interne napake. %1 bo skuÅ¡al varno nadaljevati. To je nepriÄakovana napaka, ki jo lahko prijavite, kot je opisano spodaj.</translation>
- </message>
-</context>
+ </context>
<context>
<name>QObject</name>
<message>
@@ -345,46 +333,46 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform>%n sekunda</numerusform>
- <numerusform>%n sekundi</numerusform>
- <numerusform>%n sekunde</numerusform>
- <numerusform>%n sekund</numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform>%n minuta</numerusform>
- <numerusform>%n minuti</numerusform>
- <numerusform>%n minute</numerusform>
- <numerusform>%n minut </numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform>%n ura</numerusform>
- <numerusform>%n uri</numerusform>
- <numerusform>%n ure</numerusform>
- <numerusform>%n ur</numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform>%n dan</numerusform>
- <numerusform>%n dni</numerusform>
- <numerusform>%n dni</numerusform>
- <numerusform>%n dni</numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform>%n teden</numerusform>
- <numerusform>%n tedna</numerusform>
- <numerusform>%n tedni</numerusform>
- <numerusform>%n tednov</numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message>
@@ -394,10 +382,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform>%n leto</numerusform>
- <numerusform>%n leti</numerusform>
- <numerusform>%n leta</numerusform>
- <numerusform>%n let</numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
</context>
@@ -464,10 +452,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Napaka: podedovane denarnice podpirajo le naslove vrst "legacy", "p2sh-segwit" in "bech32".</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Napaka: ni mogoÄe biti odprt za dohodne povezave (vrnjena napaka: %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Ocena provizije ni uspela. Uporaba nadomestne provizije (fallback fee) je onemogoÄena. PoÄakajte nekaj blokov ali omogoÄite -fallbackfee.</translation>
</message>
@@ -512,6 +496,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Obrezovanje ne sme biti nastavljeno pod %d miB. Prosimo, uporabite veÄjo Å¡tevilko.</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">NaÄin obrezovanja ni združljiv z možnostjo -reindex-chainstate. Namesto tega uporabite polni -reindex.</translation>
+ </message>
+ <message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished">Obrezovanje: zadnja sinhronizacija denarnice je izven obrezanih podatkov. Izvesti morate -reindex (v primeru obrezanega naÄina delovanja bo potrebno znova prenesti celotno verigo blokov).</translation>
</message>
@@ -564,6 +552,14 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Nastavljena je neznana oblika datoteke denarnice "%s". Prosimo, uporabite "bdb" ali "sqlite".</translation>
</message>
<message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Podatkovna baza stanja verige (chainstate) je v formatu, ki ni podprt. Prosimo, ponovno zaženite program z možnostjo -reindex-chainstate. S tem bo baza stanja verige zgrajena ponovno.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Denarnica uspeÅ¡no ustvarjena. Podedovani tip denarnice je zastarel in v opuÅ¡Äanju. Podpora za tvorbo in odpiranje denarnic podedovanega tipa bo v prihodnosti odstranjena.</translation>
+ </message>
+ <message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
<translation type="unfinished">Opozorilo: oblika izvozne (dump) datoteke "%s" ne ustreza obliki "%s", izbrani v ukazni vrstici.</translation>
</message>
@@ -612,6 +608,22 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Nadgradnja -txindex je bila zaÄeta s prejÅ¡njo razliÄico programske opreme in je ni mogoÄe dokonÄati. Poskusite ponovno s prejÅ¡njo razliÄico ali pa zaženite poln -reindex.</translation>
</message>
<message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Možnost -reindex-chainstate ni združljiva z -blockfilterindex. Prosimo, ali zaÄasno onemogoÄite blockfilterindex in uporabite -reindex-chainstate ali pa namesto reindex-chainstate uporabite -reindex za popolno ponovno tvorbo vseh kazal.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Možnost -reindex-chainstate option ni združljiva z -coinstatsindex. Prosimo, ali zaÄasno onemogoÄite coinstatsindex in uporabite -reindex-chainstate ali pa namesto reindex-chainstate uporabite -reindex za popolno ponovno tvorbo vseh kazal.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Možnost -reindex-chainstate option ni združljiva s -txindex. Prosimo, ali zaÄasno onemogoÄite txindex in uporabite -reindex-chainstate ali pa namesto reindex-chainstate uporabite -reindex za popolno ponovno tvorbo vseh kazal.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Zadnja sinhronizacija denarnice pade izven obdobja blokov, katerih podatki so na voljo. Potrebno je poÄakati, da preverjanje v ozadju prenese potrebne bloke.</translation>
+ </message>
+ <message>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
<translation type="unfinished">Nezdružljivi nastavitvi: navedene so specifiÄne povezave in hkrati se uporablja addrman za iskanje izhodnih povezav.</translation>
</message>
@@ -620,6 +632,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Napaka pri nalaganu %s: Denarnica za zunanje podpisovanje naložena, podpora za zunanje podpisovanje pa ni prevedena</translation>
</message>
<message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Preimenovanje neveljavne datoteke peers.dat je spodletelo. Prosimo, premaknite ali izbrišite jo in poskusite znova.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">Konfiguracijske nastavitve za %s se na omrežju %s upoÅ¡tevajo le, Äe so zapisane v odseku [%s].</translation>
</message>
@@ -696,10 +712,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Napaka pri branju naslednjega zapisa v podatkovni bazi denarnice.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Napaka pri nadgradnji baze podatkov stanja verige.</translation>
- </message>
- <message>
<source>Error: Couldn't create cursor into database</source>
<translation type="unfinished">Napaka: ne morem ustvariti kurzorja v bazo</translation>
</message>
@@ -848,10 +860,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Noben naslov ni na voljo</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Posredniški strežnik (proxy) ni nastavljen. Uporabite -proxy=&lt;ip&gt; ali -proxy=&lt;ip:port&gt;.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Na voljo ni dovolj deskriptorjev datotek.</translation>
</message>
@@ -860,10 +868,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Negativne vrednosti parametra funkcije obrezovanja niso sprejemljive.</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Funkcija obrezovanja ni združljiva z opcijo -coinstatsindex.</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">Funkcija obrezovanja ni združljiva z opcijo -txindex.</translation>
</message>
@@ -984,6 +988,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Transkacija je prevelika</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Spodletelo je dodeljevanje pomnilnika za -maxsigcachesize: '%s' MiB</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished">Na tem raÄunalniku ni bilo mogoÄe vezati naslova %s (vrnjena napaka: %s)</translation>
</message>
@@ -1040,10 +1048,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Nepodprta kategorija beleženja %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Nadgrajujem podatkovno bazo UTXO (nepotrošenih kovancev)</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Komentar uporabniškega agenta (%s) vsebuje nevarne znake.</translation>
</message>
@@ -1187,16 +1191,32 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<source>&amp;Load PSBT from file…</source>
<translation type="unfinished">&amp;Naloži DPBT iz datoteke...</translation>
</message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Sinhroniziram zaglavja (%1 %)…</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Sinhroniziram z omrežjem...</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation type="unfinished">&amp;Možnosti iz ukazne vrstice</translation>
+ </message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform>Obdelan je %n blok zgodovine transakcij.</numerusform>
- <numerusform>Obdelana sta %n bloka zgodovine transakcij.</numerusform>
- <numerusform>Obdelani so %n bloki zgodovine transakcij.</numerusform>
- <numerusform>Obdelanih je %n blokov zgodovine transakcij.</numerusform>
+ <numerusform>Obdelan %n blok zgodovine transakcij.</numerusform>
+ <numerusform>Obdelana %n bloka zgodovine transakcij.</numerusform>
+ <numerusform>Obdelani %n bloki zgodovine transakcij.</numerusform>
+ <numerusform>Obdelanih %n blokov zgodovine transakcij.</numerusform>
</translation>
</message>
<message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">Naloži delno podpisano bitcoin-transakcijo</translation>
+ </message>
+ <message>
<source>Load PSBT from &amp;clipboard…</source>
<translation type="unfinished">Naloži DPBT z &amp;odložiÅ¡Äa...</translation>
</message>
@@ -1237,6 +1257,16 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Zapri denarnico</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Obnovi denarnico...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Obnovi denarnico iz datoteke z varnostno kopijo</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Zapri vse denarnice</translation>
</message>
@@ -1261,6 +1291,26 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Ni denarnic na voljo</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Podatki o denarnici</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Naloži varnostno kopijo denarnice</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Obnovi denarnico</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Ime denarnice</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">O&amp;kno</translation>
</message>
@@ -1276,10 +1326,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform>%n aktivna povezava v omrežje bitcoin</numerusform>
- <numerusform>%n aktivni povezavi v omrežje bitcoin</numerusform>
- <numerusform>%n aktivne povezave v omrežje bitcoin</numerusform>
- <numerusform>%n aktivnih povezav v omrežje bitcoin</numerusform>
+ <numerusform>%n aktivna povezava v omrežje bitcoin. </numerusform>
+ <numerusform>%n aktivni povezavi v omrežje bitcoin.</numerusform>
+ <numerusform>%n aktivne povezave v omrežje bitcoin.</numerusform>
+ <numerusform>%n aktivnih povezav v omrežje bitcoin.</numerusform>
</translation>
</message>
<message>
@@ -1303,6 +1353,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">OmogoÄi omrežno aktivnost</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Predsinhronizacija zaglavij (%1 %)...</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Napaka: %1</translation>
</message>
@@ -1557,6 +1611,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<source>Can't list signers</source>
<translation type="unfinished">Ne morem našteti podpisnikov</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Zunanjih podpisnikov je preveÄ</translation>
+ </message>
</context>
<context>
<name>LoadWalletsActivity</name>
@@ -1597,6 +1655,34 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Obnovi denarnico</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Obnavljanje denarnice &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Obnova denarnice je spodletela</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Obnova denarnice - opozorilo</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Obnova denarnice - sporoÄilo</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1771,13 +1857,32 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
</context>
<context>
<name>Intro</name>
- <message>
- <source>%1 GB of space available</source>
- <translation type="unfinished">Na voljo je %1 GB prostora.</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(od potrebnih %1 GB)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1791,10 +1896,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform>(dovolj za obnovitev varnostnih kopij, starih %n dan)</numerusform>
- <numerusform>(dovolj za obnovitev varnostnih kopij, starih %n dni)</numerusform>
- <numerusform>(dovolj za obnovitev varnostnih kopij, starih %n dni)</numerusform>
- <numerusform>(dovolj za obnovitev varnostnih kopij, starih %n dni)</numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message>
@@ -1810,10 +1915,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Napaka: Ni mogoÄe ustvariti mape "%1".</translation>
</message>
<message>
- <source>Error</source>
- <translation type="unfinished">Napaka</translation>
- </message>
- <message>
<source>Welcome</source>
<translation type="unfinished">Dobrodošli</translation>
</message>
@@ -1826,10 +1927,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Ker ste program zagnali prviÄ, lahko izberete, kje bo %1 shranil podatke.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Ko kliknete OK, bo %1 zaÄel prenaÅ¡ati podatke in procesirati celotno verigo blokov %4 (%2 GB), zaÄenÅ¡i z najstarejÅ¡o transakcijo iz %3 ob prvotnem zaÄetku %4.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Omeji velikost shrambe verige blokov na </translation>
</message>
@@ -1842,6 +1939,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">ZaÄetna sinhronizacija je zelo zahtevna in lahko odkrije probleme s strojno opremo v vaÅ¡em raÄunalniku, ki so prej bili neopaženi. VsakiÄ, ko zaženete %1, bo le-ta nadaljeval s prenosom, kjer je prejÅ¡njiÄ ostal.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">Ko kliknete OK, bo %1 priÄel prenaÅ¡ati in obdelovati celotno verigo blokov %4 (%2 GB), zaÄenÅ¡i s prvimi transakcijami iz %3, ko je bil %4 zagnan.</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished">ÄŒe ste se odloÄili omejiti shranjevanje blokovnih verig (obrezovanje), je treba zgodovinske podatke Å¡e vedno prenesti in obdelati, vendar bodo kasneje izbrisani, da bo poraba prostora nizka.</translation>
</message>
@@ -1934,6 +2035,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">Neznano. Sinhroniziram zaglavja (%1, %2%)...</translation>
</message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Neznano. Predsinhronizacija zaglavij (%1, %2 %)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1990,6 +2095,10 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">Ko zaprete glavno okno programa, bo program tekel Å¡e naprej, okno pa bo zgolj minimirano. Program v tem primeru ustavite tako, da v meniju izberete ukaz Izhod.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Možnosti, nastavljene v tem oknu, preglasi ukazna vrstica:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Odpri %1 konfiguracijsko datoteko iz delovne podatkovne mape.</translation>
</message>
@@ -2218,10 +2327,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">najboljše ujemanje "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Možnosti, nastavljene v tem pogovornem oknu, ki so bile preglašene v ukazni vrstici ali konfiguracijski datoteki:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;V redu</translation>
</message>
@@ -2244,14 +2349,22 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Potrdi ponastavitev</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Za udejanjenje sprememb je potreben ponoven zagon programa.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Trenutne nastavitve bodo varnostno shranjene na mesto "%1".</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Program bo zaustavljen. Želite nadaljevati z izhodom?</translation>
</message>
<message>
@@ -2273,10 +2386,6 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
<translation type="unfinished">PrekliÄi</translation>
</message>
<message>
- <source>Error</source>
- <translation type="unfinished">Napaka</translation>
- </message>
- <message>
<source>The configuration file could not be opened.</source>
<translation type="unfinished">Konfiguracijske datoteke ni bilo moÄ odpreti.</translation>
</message>
@@ -2290,6 +2399,13 @@ Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Branje nastavitve "%1" je spodletelo, %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2553,6 +2669,11 @@ Svetujemo, da prodajalca prosite, naj vam priskrbi URI na podlagi BIP21.</transl
<translation type="unfinished">Soležnik</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Starost</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Smer povezave</translation>
@@ -2753,29 +2874,32 @@ Svetujemo, da prodajalca prosite, naj vam priskrbi URI na podlagi BIP21.</transl
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Ali temu soležniku posredujemo naslove</translation>
</message>
<message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Posrednik naslovov</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">Skupno Å¡tevilo obdelanih naslovov, razen opuÅ¡Äenih zaradi omejitev hitrosti</translation>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Skupno število obdelanih naslovov, prejetih od tega soležnika (naslovi, ki niso bili sprejeti zaradi omejevanja gostote komunikacije, niso šteti).</translation>
</message>
<message>
- <source>Addresses Processed</source>
- <translation type="unfinished">Obdelanih naslovov</translation>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Skupno število naslovov, prejetih od tega soležnika, ki so bili zavrnjeni (niso bili obdelani) zaradi omejevanja gostote komunikacije.</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">Skupno Å¡tevilo naslovov, opuÅ¡Äenih zaradi omejitev hitrosti</translation>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Obdelanih naslovov</translation>
</message>
<message>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">Omejenih naslovov</translation>
</message>
<message>
@@ -3389,10 +3513,6 @@ Opomba: Ker se provizija izraÄuna na bajt, bi provizija "100 satoshijev na kvB"
<translation type="unfinished">Kopiraj koliÄino</translation>
</message>
<message>
- <source>Copy amount</source>
- <translation type="unfinished">Kopiraj znesek</translation>
- </message>
- <message>
<source>Copy fee</source>
<translation type="unfinished">Kopiraj provizijo</translation>
</message>
@@ -3561,17 +3681,13 @@ Opomba: Ker se provizija izraÄuna na bajt, bi provizija "100 satoshijev na kvB"
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Provizija, ki je veÄja od %1, velja za nesmiselno veliko.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Zahtevek za plaÄilo je potekel.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform>Predviden priÄetek potrjevanja v naslednjem %n bloku.</numerusform>
- <numerusform>Predviden priÄetek potrjevanja v naslednjih %n blokih.</numerusform>
- <numerusform>Predviden priÄetek potrjevanja v naslednjih %n blokih.</numerusform>
- <numerusform>Predviden priÄetek potrjevanja v naslednjih %n blokih.</numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message>
@@ -3646,14 +3762,6 @@ Opomba: Ker se provizija izraÄuna na bajt, bi provizija "100 satoshijev na kvB"
<translation type="unfinished">SporoÄilo:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Ta zahtevek za plaÄilo je neoverjen.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Ta zahtevek za plaÄilo je overjen.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Če vnesete oznako za zgornji naslov, se bo skupaj z naslovom shranila v imenik že uporabljenih naslovov</translation>
</message>
@@ -3661,14 +3769,6 @@ Opomba: Ker se provizija izraÄuna na bajt, bi provizija "100 satoshijev na kvB"
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">SporoÄilo, ki je bilo pripeto na URI tipa bitcoin: in bo shranjeno skupaj s podatki o transakciji. Opomba: SporoÄilo ne bo poslano preko omrežja Bitcoin.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Prejemnik:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Opomba:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3835,30 +3935,32 @@ Opomba: Ker se provizija izraÄuna na bajt, bi provizija "100 satoshijev na kvB"
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">v sporu s transakcijo z %1 potrditvami</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/nepotrjeno, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">v Äakalni vrsti</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0 / nepotrjena, v Äakalni vrsti</translation>
</message>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">ni v Äakalni vrsti</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0 / nepotrjena, ni v Äakalni vrsti</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">opuÅ¡Äena</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/nepotrjena</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 potrditev</translation>
</message>
<message>
@@ -3908,10 +4010,10 @@ Opomba: Ker se provizija izraÄuna na bajt, bi provizija "100 satoshijev na kvB"
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform>Dozori v %n bloku</numerusform>
- <numerusform>Dozori v naslednjih %n blokih</numerusform>
- <numerusform>Dozori v naslednjih %n blokih</numerusform>
- <numerusform>Dozori v naslednjih %n blokih</numerusform>
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ <numerusform />
</translation>
</message>
<message>
@@ -4219,7 +4321,7 @@ Opomba: Ker se provizija izraÄuna na bajt, bi provizija "100 satoshijev na kvB"
<message>
<source>Comma separated file</source>
<extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
- <translation type="unfinished">Datoteka CSV (podatki loÄeni z vejicami)</translation>
+ <translation type="unfinished">Vrednosti loÄene z vejicami</translation>
</message>
<message>
<source>Confirmed</source>
@@ -4285,10 +4387,6 @@ Za odpiranje denarnice kliknite Datoteka &gt; Odpri denarnico
<translation type="unfinished">Ustvari novo denarnico</translation>
</message>
<message>
- <source>Error</source>
- <translation type="unfinished">Napaka</translation>
- </message>
- <message>
<source>Unable to decode PSBT from clipboard (invalid base64)</source>
<translation type="unfinished">Ne morem dekodirati DPBT z odložiÅ¡Äa (neveljaven format base64)</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sn.ts b/src/qt/locale/bitcoin_sn.ts
index ca55e7429f..40abe38b4e 100644
--- a/src/qt/locale/bitcoin_sn.ts
+++ b/src/qt/locale/bitcoin_sn.ts
@@ -212,6 +212,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts
index 0dd48a1cae..9efa2971eb 100644
--- a/src/qt/locale/bitcoin_sq.ts
+++ b/src/qt/locale/bitcoin_sq.ts
@@ -455,6 +455,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -652,10 +673,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Paste address from clipboard</source>
<translation type="unfinished">Ngjit nga memorja e sistemit</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Paguaj drejt:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -668,10 +685,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/I pakonfirmuar</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 konfirmimet</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts
index 1b3763d0ae..d33c25ac3b 100644
--- a/src/qt/locale/bitcoin_sr.ts
+++ b/src/qt/locale/bitcoin_sr.ts
@@ -92,6 +92,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Извези ЛиÑту ÐдреÑа</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">CSV фајл</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">ДеÑила Ñе грешка приликом покушаја да Ñе лиÑта адреÑа упамти на %1. Молимо покушајте поново.</translation>
@@ -241,10 +246,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">Изузетак покретања</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">Дошло је до фаталне грешке. 1%1 даље не може безбедно да наÑтави, те ће Ñе угаÑити.</translation>
+ </message>
+ <message>
<source>Internal error</source>
<translation type="unfinished">Интерна грешка</translation>
</message>
- </context>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">Догодила Ñе интерна грешка. %1 ће покушати да наÑтави безбедно. Ово је неочекивана грешка која може да Ñе пријави као што је објашњено иÑпод.</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
@@ -256,6 +273,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Грешка: %1</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">1%1 још увек није изашао безбедно…</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation type="unfinished">непознато</translation>
</message>
@@ -268,6 +289,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">УнеÑи Биткоин адреÑу, (нпр %1)</translation>
</message>
<message>
+ <source>Unroutable</source>
+ <translation type="unfinished">Ðемогуће преуÑмерити</translation>
+ </message>
+ <message>
+ <source>Internal</source>
+ <translation type="unfinished">Унутрашње</translation>
+ </message>
+ <message>
<source>Inbound</source>
<extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
<translation type="unfinished">Долазеће</translation>
@@ -278,6 +307,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Одлазеће</translation>
</message>
<message>
+ <source>Full Relay</source>
+ <extracomment>Peer connection type that relays all network information.</extracomment>
+ <translation type="unfinished">Потпуна предаја</translation>
+ </message>
+ <message>
+ <source>Block Relay</source>
+ <extracomment>Peer connection type that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">Блокирана предаја</translation>
+ </message>
+ <message>
+ <source>Manual</source>
+ <extracomment>Peer connection type established manually through one of several methods.</extracomment>
+ <translation type="unfinished">УпутÑтво</translation>
+ </message>
+ <message>
+ <source>Feeler</source>
+ <extracomment>Short-lived peer connection type that tests the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Сензор</translation>
+ </message>
+ <message>
+ <source>Address Fetch</source>
+ <extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
+ <translation type="unfinished">Преузимање адреÑе</translation>
+ </message>
+ <message>
<source>None</source>
<translation type="unfinished">Nijedan</translation>
</message>
@@ -337,10 +391,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<numerusform />
</translation>
</message>
+ <message>
+ <source>%1 kB</source>
+ <translation type="unfinished">%1 килобајта</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Фајл Ñа подешавањима Ñе не може прочитати</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Фајл Ñа подешавањима Ñе не може запиÑати</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">%s девелопери</translation>
</message>
@@ -361,10 +427,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Грешка у читању %s! Сви кључеви Ñу прочитани коректно, али подаци о транÑакцији или уноÑи у адреÑар могу недоÑтајати или бити нетачни.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Грешка: Претрага за долазним конекцијама није уÑпела (претрага враћа грешку %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Процена провизије није уÑпела. Промена провизије током транÑакције је онемогућена. Сачекајте неколико блокова или омогућите -fallbackfee.</translation>
</message>
@@ -513,10 +575,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Грешка приликом читања из базе података, иÑкључивање у току.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Грешка приликом надоградње базе података Ñтања ланца</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Грешка: ПроÑтор на диÑку је мали за %s</translation>
</message>
@@ -705,10 +763,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Категорија запиÑа није подржана %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Ðадоградња UTXO базе података</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Коментар агента кориÑника (%s) Ñадржи небезбедне знакове.</translation>
</message>
@@ -837,6 +891,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Верификуј поруке и утврди да ли Ñу потпиÑане од Ñтране Ñпецификованих Биткоин адреÑа</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">&amp;Учитава â€PSBT†из датотеке…</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">Отвори &amp;URI</translation>
+ </message>
+ <message>
<source>Close Wallet…</source>
<translation type="unfinished">Затвори новчаник...</translation>
</message>
@@ -869,6 +931,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Синхронизација Ñа мрежом...</translation>
</message>
<message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">ИндекÑирање блокова на диÑку…</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">ПроцеÑуирање блокова на диÑку</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">РеиндекÑирање блокова на диÑку…</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">Повезивање Ñа клијентима...</translation>
+ </message>
+ <message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished">Затражи плаћање (генерише QR кодове и биткоин: URI-е)</translation>
</message>
@@ -897,6 +975,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1 уназад</translation>
</message>
<message>
+ <source>Catching up…</source>
+ <translation type="unfinished">Ðжурирање у току...</translation>
+ </message>
+ <message>
<source>Last received block was generated %1 ago.</source>
<translation type="unfinished">ПоÑледњи примљени блок је направљен пре %1.</translation>
</message>
@@ -921,6 +1003,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðжурирано</translation>
</message>
<message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">Учитај делимично потпиÑану Bitcoin транÑакцију</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation type="unfinished">Учитај делимично потпиÑану Bitcoin транÑакцију из clipboard-a</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation type="unfinished">Ðоде прозор</translation>
</message>
@@ -961,6 +1051,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Прикажи поруку помоћи %1 за лиÑту Ñа могућим опцијама Биткоин командне линије</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">&amp;МаÑкирај вредноÑти</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">Филтрирај вредноÑти у картици за преглед</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation type="unfinished">подразумевани новчаник</translation>
</message>
@@ -969,6 +1067,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðема доÑтупних новчаника</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Име Ðовчаника</translation>
+ </message>
+ <message>
<source>Zoom</source>
<translation type="unfinished">Увећај</translation>
</message>
@@ -980,6 +1083,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 клијент</translation>
</message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">&amp;Прикажи</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -990,6 +1097,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Клик за више акција</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">Прикажи картицу Ñа â€ÐšÐ»Ð¸Ñ˜ÐµÐ½Ñ‚имаâ€</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">Онемогући мрежне активноÑти</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">Омогући мрежне активноÑти</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Грешка: %1</translation>
</message>
@@ -1148,6 +1275,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Копирај изноÑ</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Копирај адреÑу</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копирај &amp;означи</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Копирај &amp;изноÑ</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">Закључај непотрошено</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">Откључај непотрошено</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">Копирај количину</translation>
</message>
@@ -1219,6 +1366,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Create wallet warning</source>
<translation type="unfinished">Ðаправи упозорење за новчаник</translation>
</message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Ðе могу да излиÑтам потпиÑнике</translation>
+ </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1239,7 +1390,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">Отвори новчаник</translation>
</message>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">Отвањаре новчаника &lt;b&gt;%1&lt;/b&gt;</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
@@ -1286,6 +1442,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Шифрирај новчаник</translation>
</message>
<message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">Ðапредне опције</translation>
+ </message>
+ <message>
<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">Онемогући приватни кључ за овај новчаник. Ðовчаници Ñа онемогућеним приватним кључем неће имати приватни кључ и не могу имати HD Ñеме или увезени приватни кључ. Ова опција идеална је за новчанике који Ñу иÑкључиво за поÑматрање.</translation>
</message>
@@ -1302,10 +1462,36 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðаправи Празан Ðовчаник</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation type="unfinished">КориÑтите деÑкрипторе за управљање ÑцриптПубКеи-ом</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">ДеÑкриптор Ðовчаник</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">ЕкÑтерни потпиÑник</translation>
+ </message>
+ <message>
<source>Create</source>
<translation type="unfinished">Ðаправи</translation>
</message>
- </context>
+ <message>
+ <source>Compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished">СаÑтављено без Ñклите подршке (потребно за новчанике деÑкриптора)</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">СаÑтављено без подршке за Ñпољно потпиÑивање (потребно за Ñпољно потпиÑивање)</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -1390,6 +1576,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Bitcoin</source>
<translation type="unfinished">Биткоин</translation>
</message>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Ðајмање %1 GB подататака биће Ñкладиштен у овај директорјиум који ће временом пораÑти.</translation>
@@ -1436,14 +1646,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Пошто је ово први пут да је програм покренут, можете изабрати где ће %1 чувати Ñвоје податке.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Када кликнете на ОК, %1 ће почети Ñ Ð¿Ñ€ÐµÑƒÐ·Ð¸Ð¼Ð°ÑšÐµÐ¼ и процеÑуирањем целокупног ланца блокова %4 (%2GB), почевши од најранијих транÑакција у %3 када је %4 покренут.</translation>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">Ограничите Ñкладиштење блок ланца на</translation>
</message>
<message>
<source>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>
<translation type="unfinished">Враћање ове опције захтева поновно преузимање целокупног блокчејна - ланца блокова. Брже је преузети цели ланац и каÑније га Ñкратити. Онемогућава неке напредне опције.</translation>
</message>
<message>
+ <source> GB</source>
+ <translation type="unfinished">Гигабајт</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">Првобитна Ñинхронизација веома је захтевна и може изложити ваш рачунар хардверÑким проблемима који раније ниÑу били примећени. Сваки пут када покренете %1, преузимање ће Ñе наÑтавити тамо где је било прекинуто.</translation>
</message>
@@ -1540,6 +1754,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
<translation type="unfinished">%1 Ñе Ñинхронузује. Преузеће заглавља и блокове од клијената и потврдити их док не Ñтигне на крај ланца блокова.</translation>
</message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Ðепознато. Синхронизација заглавља (%1, %2%)...</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1572,6 +1790,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Покрени %1 приликом пријаве на ÑиÑтем</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Омогућавање Ñмањења значајно Ñмањује проÑтор на диÑку потребан за Ñкладиштење транÑакција. Сви блокови Ñу још увек у потпуноÑти валидирани. Враћање ове поÑтавке захтева поновно преузимање целог блоцкцхаина.</translation>
+ </message>
+ <message>
<source>Size of &amp;database cache</source>
<translation type="unfinished">Величина кеша базе података</translation>
</message>
@@ -1644,6 +1866,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Троши непотврђени куÑур</translation>
</message>
<message>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">ЕкÑтерни потпиÑник (нпр. хардверÑки новчаник)</translation>
+ </message>
+ <message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">&amp;Путања Ñкрипте Ñпољног потпиÑника</translation>
+ </message>
+ <message>
+ <source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
+ <translation type="unfinished">Пуна путања до Ñкрипте компатибилне Ñа Битцоин Цоре (нпр. Ц:\ДовнлоадÑ\хви.еке или /УÑерÑ/иоу/ДовнлоадÑ/хви.пи). Пазите: злонамерни Ñофтвер може украÑти ваше новчиће</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">ÐутоматÑки отвори Биткоин клијент порт на рутеру. Ова опција ради Ñамо уколико твој рутер подржава и има омогућен UPnP.</translation>
</message>
@@ -1652,6 +1886,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Мапирај порт кориÑтећи &amp;UPnP</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">ÐутоматÑки отворите порт за Битцоин клијент на рутеру. Ово функционише Ñамо када ваш рутер подржава ÐÐТ-ПМП и када је омогућен. Спољни порт би могао бити наÑумичан.</translation>
+ </message>
+ <message>
+ <source>Map port using NA&amp;T-PMP</source>
+ <translation type="unfinished">Мапирајте порт кориÑтећи ÐÐ&amp;Т-ПМП</translation>
+ </message>
+ <message>
<source>Accept connections from outside.</source>
<translation type="unfinished">Прихвати Ñпољашње концекције.</translation>
</message>
@@ -1688,6 +1930,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Тор</translation>
</message>
<message>
+ <source>Show the icon in the system tray.</source>
+ <translation type="unfinished">Прикажите икону у ÑиÑтемÑкој палети.</translation>
+ </message>
+ <message>
+ <source>&amp;Show tray icon</source>
+ <translation type="unfinished">&amp;Прикажи икону у траци</translation>
+ </message>
+ <message>
<source>Show only a tray icon after minimizing the window.</source>
<translation type="unfinished">Покажи Ñамо иконицу у панелу након минимизирања прозора</translation>
</message>
@@ -1724,8 +1974,24 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Да ли да Ñе прикажу опције контроле новчића или не.</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Опције поÑтављене у овом диалогу Ñу поништене командном линијом или у конфигурационој датотеци:</translation>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation type="unfinished">Повежите Ñе на Битцоин мрежу преко заÑебног СОЦКС5 прокÑија за Тор онион уÑлуге.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation type="unfinished">КориÑтите поÑебан СОЦКС&amp;5 прокÑи да биÑте дошли до вршњака преко уÑлуга Тор онион:</translation>
+ </message>
+ <message>
+ <source>Monospaced font in the Overview tab:</source>
+ <translation type="unfinished">Једноразредни фонт на картици Преглед:</translation>
+ </message>
+ <message>
+ <source>embedded "%1"</source>
+ <translation type="unfinished">уграђено â€%1â€</translation>
+ </message>
+ <message>
+ <source>closest matching "%1"</source>
+ <translation type="unfinished">Ðајближа ÑличноÑÑ‚ â€%1â€</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -1736,6 +2002,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;Откажи</translation>
</message>
<message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">СаÑтављено без подршке за Ñпољно потпиÑивање (потребно за Ñпољно потпиÑивање)</translation>
+ </message>
+ <message>
<source>default</source>
<translation type="unfinished">подразумевано</translation>
</message>
@@ -1745,14 +2016,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Потврди реÑет опција</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">РеÑтарт клијента захтеван како би Ñе промене активирале.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Клијент ће Ñе иÑкључити. Да ли желите да наÑтавите?</translation>
</message>
<message>
@@ -1860,7 +2134,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Current total balance in watch-only addresses</source>
<translation type="unfinished">Тренутни укупни Ñалдо у адреÑама у опцији Ñамо-гледај</translation>
</message>
- </context>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation type="unfinished">Режим приватноÑти је активиран за картицу Преглед. Да биÑте демаÑкирали вредноÑти, поништите избор Подешавања-&gt;МаÑк вредноÑти.</translation>
+ </message>
+</context>
<context>
<name>PSBTOperationsDialog</name>
<message>
@@ -1888,10 +2166,67 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Затвори</translation>
</message>
<message>
+ <source>Failed to load transaction: %1</source>
+ <translation type="unfinished">ÐеуÑпело учитавање транÑакције: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation type="unfinished">ÐеуÑпело потпиÑивање транÑакције: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation type="unfinished">Ðије могуће потпиÑати више уноÑа.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation type="unfinished">ПотпиÑано %1 поље, али је потребно још потпиÑа.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation type="unfinished">ПотпиÑана транÑакција је уÑпешно. ТранÑакција је Ñпремна за емитовање.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation type="unfinished">Ðепозната грешка у обради транÑакције.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation type="unfinished">ТранÑакција је уÑпешно емитована! Идентификација транÑакције (ID): %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation type="unfinished">ÐеуÑпело емитовање транÑакције: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation type="unfinished">ПСБТ је копиран у међуÑпремник.</translation>
+ </message>
+ <message>
<source>Save Transaction Data</source>
<translation type="unfinished">Сачувај Податке ТранÑакције</translation>
</message>
<message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">Делимично потпиÑана транÑакција (бинарна)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation type="unfinished">ПСБТ је Ñачуван на диÑку.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation type="unfinished">*Шаље %1 до %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation type="unfinished">Ðије могуће израчунати накнаду за транÑакцију или укупан Ð¸Ð·Ð½Ð¾Ñ Ñ‚Ñ€Ð°Ð½Ñакције.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation type="unfinished">Плаћа накнаду за транÑакцију:</translation>
+ </message>
+ <message>
<source>Total Amount</source>
<translation type="unfinished">Укупан изноÑ</translation>
</message>
@@ -1900,6 +2235,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">или</translation>
</message>
<message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation type="unfinished">ТранÑакција има %1 непотпиÑана поља.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation type="unfinished">ТранÑакцији недоÑтају неке информације о улазима.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation type="unfinished">ТранÑакција и даље треба потпиÑ(е).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation type="unfinished">(Ðли овај новчаник не може да потпиÑује транÑакције.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation type="unfinished">(Ðли овај новчаник нема праве кључеве.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation type="unfinished">ТранÑакција је у потпуноÑти потпиÑана и Ñпремна за емитовање.</translation>
+ </message>
+ <message>
<source>Transaction status is unknown.</source>
<translation type="unfinished">Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ñ‚Ñ€Ð°Ð½Ñакције је непознат.</translation>
</message>
@@ -1923,6 +2282,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">'bitcoin://' није важећи URI. УмеÑто тога кориÑтити 'bitcoin:'.</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.
+Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
+If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation type="unfinished">Ðије могуће обрадити захтев за плаћање јер БИП70 није подржан.
+Због широко раÑпроÑтрањених безбедноÑних пропуÑта у БИП70, топло Ñе препоручује да Ñе игноришу Ñва упутÑтва трговца за промену новчаника.
+Ðко добијете ову грешку, требало би да затражите од трговца да доÑтави УРИ компатибилан Ñа БИП21.</translation>
+ </message>
+ <message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
<translation type="unfinished">URI Ñе не може рашчланити! Ово може бити проузроковано неважећом Биткоин адреÑом или погрешно форматираним URI параметрима.</translation>
</message>
@@ -1944,6 +2311,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Пинг</translation>
</message>
<message>
+ <source>Peer</source>
+ <extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
+ <translation type="unfinished">Пеер</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Правац</translation>
@@ -1987,6 +2359,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>QRImageWidget</name>
<message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">&amp;Сачували Ñлику…</translation>
+ </message>
+ <message>
<source>&amp;Copy Image</source>
<translation type="unfinished">&amp;Копирај Слику</translation>
</message>
@@ -2006,7 +2382,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Save QR Code</source>
<translation type="unfinished">Упамти QR Код</translation>
</message>
- </context>
+ <message>
+ <source>PNG Image</source>
+ <extracomment>Expanded name of the PNG file format. See: https://en.wikipedia.org/wiki/Portable_Network_Graphics.</extracomment>
+ <translation type="unfinished">ПÐГ Ñлика</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
@@ -2130,6 +2511,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðоде прозор</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation type="unfinished">Тренутна виÑина блока</translation>
+ </message>
+ <message>
<source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
<translation type="unfinished">Отворите %1 датотеку Ñа запиÑима о отклоњеним грешкама из тренутног директоријума датотека. Ово може потрајати неколико Ñекунди за велике датотеке запиÑа.</translation>
</message>
@@ -2142,14 +2527,59 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Увећај величину фонта</translation>
</message>
<message>
+ <source>Permissions</source>
+ <translation type="unfinished">Дозволе</translation>
+ </message>
+ <message>
+ <source>The direction and type of peer connection: %1</source>
+ <translation type="unfinished">Смер и тип конекције клијената: %1</translation>
+ </message>
+ <message>
+ <source>Direction/Type</source>
+ <translation type="unfinished">Смер/Тип</translation>
+ </message>
+ <message>
+ <source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
+ <translation type="unfinished">Мрежни протокол који је овај пеер повезан преко: ИПв4, ИПв6, Онион, И2П или ЦЈДÐС.</translation>
+ </message>
+ <message>
<source>Services</source>
<translation type="unfinished">УÑлуге</translation>
</message>
<message>
+ <source>Whether the peer requested us to relay transactions.</source>
+ <translation type="unfinished">Да ли је колега тражио од Ð½Ð°Ñ Ð´Ð° пренеÑемо транÑакције</translation>
+ </message>
+ <message>
+ <source>Wants Tx Relay</source>
+ <translation type="unfinished">Жели Тк Релаciju</translation>
+ </message>
+ <message>
+ <source>High bandwidth BIP152 compact block relay: %1</source>
+ <translation type="unfinished">ВиÑок проток â€BIP152†преноÑа компактних блокова: %1</translation>
+ </message>
+ <message>
+ <source>High Bandwidth</source>
+ <translation type="unfinished">ВиÑок проток</translation>
+ </message>
+ <message>
<source>Connection Time</source>
<translation type="unfinished">Време конекције</translation>
</message>
<message>
+ <source>Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
+ <translation type="unfinished">Прошло је време од када је нови блок који је прошао почетне провере валидноÑти примљен од овог равноправног кориÑника.</translation>
+ </message>
+ <message>
+ <source>Last Block</source>
+ <translation type="unfinished">ПоÑледњи блок</translation>
+ </message>
+ <message>
+ <source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
+ <extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
+ <translation type="unfinished">Прошло је време од када је нова транÑакција прихваћена у наш мемпул примљена од овог партнера</translation>
+ </message>
+ <message>
<source>Last Send</source>
<translation type="unfinished">ПоÑледње поÑлато</translation>
</message>
@@ -2214,6 +2644,53 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Одлазно:</translation>
</message>
<message>
+ <source>Inbound: initiated by peer</source>
+ <extracomment>Explanatory text for an inbound peer connection.</extracomment>
+ <translation type="unfinished">Долазни: покренут од Ñтране вршњака</translation>
+ </message>
+ <message>
+ <source>Outbound Full Relay: default</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</extracomment>
+ <translation type="unfinished">Одлазни пуни релеј: подразумевано</translation>
+ </message>
+ <message>
+ <source>Outbound Block Relay: does not relay transactions or addresses</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">Оутбоунд Блоцк Релаи: не преноÑи транÑакције или адреÑе</translation>
+ </message>
+ <message>
+ <source>Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Изворно упутÑтво: додато је коришћење â€RPC†%1 или %2 / %3 конфигурационих опција</translation>
+ </message>
+ <message>
+ <source>Outbound Feeler: short-lived, for testing addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">Оутбоунд Феелер: краткотрајан, за теÑтирање адреÑа</translation>
+ </message>
+ <message>
+ <source>Outbound Address Fetch: short-lived, for soliciting addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</extracomment>
+ <translation type="unfinished">Дохваћање излазне адреÑе: краткотрајно, за тражење адреÑа</translation>
+ </message>
+ <message>
+ <source>we selected the peer for high bandwidth relay</source>
+ <translation type="unfinished">одабрали Ñмо клијента за виÑок Ð¿Ñ€ÐµÐ½Ð¾Ñ Ð¿Ð¾Ð´Ð°Ñ‚Ð°ÐºÐ°</translation>
+ </message>
+ <message>
+ <source>the peer selected us for high bandwidth relay</source>
+ <translation type="unfinished">клијент Ð½Ð°Ñ Ñ˜Ðµ одабрао за виÑок Ð¿Ñ€ÐµÐ½Ð¾Ñ Ð¿Ð¾Ð´Ð°Ñ‚Ð°ÐºÐ°</translation>
+ </message>
+ <message>
+ <source>no high bandwidth relay selected</source>
+ <translation type="unfinished">није одабран проток за виÑок Ð¿Ñ€ÐµÐ½Ð¾Ñ Ð¿Ð¾Ð´Ð°Ñ‚Ð°ÐºÐ°</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;Копирај адреÑу</translation>
+ </message>
+ <message>
<source>&amp;Disconnect</source>
<translation type="unfinished">&amp;Прекини везу</translation>
</message>
@@ -2222,6 +2699,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">1 &amp;Сат</translation>
</message>
<message>
+ <source>1 d&amp;ay</source>
+ <translation type="unfinished">1 дан</translation>
+ </message>
+ <message>
<source>1 &amp;week</source>
<translation type="unfinished">1 &amp;недеља</translation>
</message>
@@ -2246,6 +2727,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Извршење команде коришћењем "%1" новчаника</translation>
</message>
<message>
+ <source>Welcome to the %1 RPC console.
+Use up and down arrows to navigate history, and %2 to clear screen.
+Use %3 and %4 to increase or decrease the font size.
+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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Добродошли у %1 "RPC†конзолу.
+КориÑти таÑтере за горе и доле да наводиш иÑторију, и %2 да очиÑтиш екран.
+КориÑти %3 и %4 да увећаш и Ñмањиш величину фонта.
+УнеÑи %5 за преглед доÑтупних комади.
+За више информација о коришћењу конзоле, притиÑни %6
+%7 УПОЗОРЕЊЕ: Преваранти Ñу Ñе активирали, говорећи кориÑницима да уноÑе команде овде, и тако краду Ñадржај новчаника. Ðе кориÑти ову конзолу без потпуног Ñхватања комплекÑноÑти ове команде. %8</translation>
+ </message>
+ <message>
+ <source>Executing…</source>
+ <extracomment>A console message indicating an entered command is currently being executed.</extracomment>
+ <translation type="unfinished">Обрада...</translation>
+ </message>
+ <message>
+ <source>(peer: %1)</source>
+ <translation type="unfinished">(клијент: %1)</translation>
+ </message>
+ <message>
<source>via %1</source>
<translation type="unfinished">преко %1</translation>
</message>
@@ -2270,6 +2776,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Забрани за</translation>
</message>
<message>
+ <source>Never</source>
+ <translation type="unfinished">Ðикада</translation>
+ </message>
+ <message>
<source>Unknown</source>
<translation type="unfinished">Ðепознато</translation>
</message>
@@ -2349,13 +2859,37 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Копирај &amp;URI</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Копирај адреÑу</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копирај &amp;означи</translation>
+ </message>
+ <message>
+ <source>Copy &amp;message</source>
+ <translation type="unfinished">Копирај &amp;поруку</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Копирај &amp;изноÑ</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">Ðовчаник није могуће откључати.</translation>
</message>
- </context>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation type="unfinished">Ðемогуће је генериÑати нову %1 адреÑу</translation>
+ </message>
+</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>Request payment to …</source>
+ <translation type="unfinished">Захтевај уплату ка ...</translation>
+ </message>
+ <message>
<source>Address:</source>
<translation type="unfinished">ÐдреÑа:</translation>
</message>
@@ -2384,6 +2918,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Копирај &amp;ÐдреÑу</translation>
</message>
<message>
+ <source>&amp;Verify</source>
+ <translation type="unfinished">&amp;Верификуј</translation>
+ </message>
+ <message>
+ <source>Verify this address on e.g. a hardware wallet screen</source>
+ <translation type="unfinished">Верификуј ову адреÑу на пример на екрану хардвер новчаника</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">&amp;Сачували Ñлику…</translation>
+ </message>
+ <message>
<source>Payment information</source>
<translation type="unfinished">Информације о плаћању</translation>
</message>
@@ -2514,14 +3060,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ОчиÑти Ñва поља форме.</translation>
</message>
<message>
+ <source>Inputs…</source>
+ <translation type="unfinished">Поља...</translation>
+ </message>
+ <message>
<source>Dust:</source>
<translation type="unfinished">Прашина:</translation>
</message>
<message>
+ <source>Choose…</source>
+ <translation type="unfinished">Одабери...</translation>
+ </message>
+ <message>
<source>Hide transaction fee settings</source>
<translation type="unfinished">Сакријте Ð¸Ð·Ð½Ð¾Ñ Ð½Ð°ÐºÐ½Ð°Ð´Ðµ за транÑакцију</translation>
</message>
<message>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation type="unfinished">Одредити прилагођену провизију по kB (1,000 битова) виртуелне величине транÑакције.
+
+Ðапомена: С обзиром да Ñе провизија рачуна на оÑнову броја бајтова, провизија за "100 Ñатошија по kB" за величину транÑакције од 500 бајтова (пола од 1 kB) ће аутоматÑки изноÑити Ñамо 50 Ñатошија.</translation>
+ </message>
+ <message>
<source>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>
<translation type="unfinished">Када је мањи обим транÑакција од проÑтора у блоку, рудари, као и повезани нодови могу применити минималну провизију. Плаћање Ñамо минималне накнаде - провизије је добро, али треба бити ÑвеÑтан да ово може резултовати транÑакцијом која неће никада бити потврђена, у Ñлучају када је број захтева за биткоин транÑакцијама већи од могућноÑти мреже да обради.</translation>
</message>
@@ -2530,6 +3092,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Сувише ниÑка провизија може резултовати да транÑакција никада не буде потврђена (прочитајте опиÑ)</translation>
</message>
<message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks…)</source>
+ <translation type="unfinished">(Паметна провизија још није покренута. Ово уобичајено траје неколико блокова...)</translation>
+ </message>
+ <message>
<source>Confirmation time target:</source>
<translation type="unfinished">Циљно време потврде:</translation>
</message>
@@ -2590,6 +3156,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1 (%2 блокова)</translation>
</message>
<message>
+ <source>Sign on device</source>
+ <extracomment>"device" usually means a hardware wallet.</extracomment>
+ <translation type="unfinished">Потпиши на уређају</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">Повежи прво Ñвој хардвер новчаник.</translation>
+ </message>
+ <message>
+ <source>Set external signer script path in Options -&gt; Wallet</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">ПодÑи екÑтерну Ñкрипту за потпиÑивање у : Options -&gt; Wallet</translation>
+ </message>
+ <message>
<source>Cr&amp;eate Unsigned</source>
<translation type="unfinished">Креирај непотпиÑано</translation>
</message>
@@ -2610,14 +3190,41 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1 до %2</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details…"</source>
+ <translation type="unfinished">Да би Ñте прегледали лиÑту примаоца кликните на "Прикажи детаље..."</translation>
+ </message>
+ <message>
+ <source>Sign failed</source>
+ <translation type="unfinished">ПотпиÑивање је неуÑпело</translation>
+ </message>
+ <message>
+ <source>External signer not found</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">ЕкÑтерни потпиÑник није пронађен</translation>
+ </message>
+ <message>
+ <source>External signer failure</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Грешка при екÑтерном потпиÑивању</translation>
+ </message>
+ <message>
<source>Save Transaction Data</source>
<translation type="unfinished">Сачувај Податке ТранÑакције</translation>
</message>
<message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">Делимично потпиÑана транÑакција (бинарна)</translation>
+ </message>
+ <message>
<source>PSBT saved</source>
<translation type="unfinished">PSBT Ñачуван</translation>
</message>
<message>
+ <source>External balance:</source>
+ <translation type="unfinished">ЕкÑтерни Ð±Ð°Ð»Ð°Ð½Ñ (Ñтање):</translation>
+ </message>
+ <message>
<source>or</source>
<translation type="unfinished">или</translation>
</message>
@@ -2626,6 +3233,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Можете повећати провизију каÑније (Ñигнали Замени-Ñа-Провизијом, BIP-125).</translation>
</message>
<message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Молимо, проверите ваш предлог транÑакције. Ово ће произвеÑти делимично потпиÑану Биткоин транÑакцију (PSBT) коју можете копирати и онда потпиÑати Ñа нпр. офлајн %1 новчаником, или PSBT компатибилним хардверÑким новчаником.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Молим, размотрите вашу транÑакцију.</translation>
@@ -2678,10 +3290,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">Провизија већа од %1 Ñе Ñматра апÑурдно виÑоком провизијом.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Захтев за плаћање је иÑтекао.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2762,14 +3370,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Порука:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Ово је неовлашћени захтев за плаћање.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Ово је овлашћени захтев за плаћање.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">УнеÑите ознаку за ову адреÑу да биÑте је додали на лиÑту коришћених адреÑа</translation>
</message>
@@ -2777,14 +3377,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Порука која је приложена биткоину: URI која ће бити Ñачувана уз транÑакцију ради референце. Ðапомена: Ова порука Ñе шаље преко Биткоин мреже.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Плати ка:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Мемо:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -2792,7 +3384,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Send</source>
<translation type="unfinished">Пошаљи</translation>
</message>
- </context>
+ <message>
+ <source>Create Unsigned</source>
+ <translation type="unfinished">Креирај непотпиÑано</translation>
+ </message>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
@@ -2933,29 +3529,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
- <name>TransactionDesc</name>
+ <name>TrafficGraphWidget</name>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/непотврђено, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">у удруженој меморији</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">није у удруженој меморији</translation>
+ <source>kB/s</source>
+ <translation type="unfinished">KB/s</translation>
</message>
+</context>
+<context>
+ <name>TransactionDesc</name>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">напуштено</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/непотврђено</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 порврде</translation>
</message>
<message>
@@ -3256,10 +3850,51 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Минимални изноÑ</translation>
</message>
<message>
+ <source>Range…</source>
+ <translation type="unfinished">ОпÑег:</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Копирај адреÑу</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">Копирај &amp;означи</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Копирај &amp;изноÑ</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">Копирај транÑакцију &amp;ID</translation>
+ </message>
+ <message>
+ <source>Copy &amp;raw transaction</source>
+ <translation type="unfinished">Копирајте &amp;необрађену транÑакцију</translation>
+ </message>
+ <message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">Копирајте Ñве детаље транÑакције</translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">&amp;Прикажи детаље транакције</translation>
+ </message>
+ <message>
+ <source>Increase transaction &amp;fee</source>
+ <translation type="unfinished">Повећај провизију транÑакције</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">Извези Детаље ТранÑакције</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">CSV фајл</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">Потврђено</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sr@latin.ts b/src/qt/locale/bitcoin_sr@latin.ts
index e57a5cbfab..a6c5122cf5 100644
--- a/src/qt/locale/bitcoin_sr@latin.ts
+++ b/src/qt/locale/bitcoin_sr@latin.ts
@@ -533,6 +533,30 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -646,10 +670,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/nepotvrdjeno</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 potvrdjeno/ih</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts
index fe707c7cec..10aab51987 100644
--- a/src/qt/locale/bitcoin_sv.ts
+++ b/src/qt/locale/bitcoin_sv.ts
@@ -70,6 +70,11 @@
<translation type="unfinished">Detta är dina Bitcoin-adresser för att skicka betalningar. Kontrollera alltid belopp och mottagaradress innan du skickar bitcoin.</translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Detta är dina Bitcoinadresser för att ta emot betalningar. Använd knappen 'Skapa ny mottagaradress' i mottagsfliken för att skapa nya adresser. Signering är bara tillgänglig för adresser av typen 'legacy'</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">&amp;Kopiera adress</translation>
</message>
@@ -244,10 +249,19 @@ Försök igen.</translation>
<source>Internal error</source>
<translation type="unfinished">Internt fel</translation>
</message>
- </context>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">Ett internt fel har uppstått. %1 kommer försöka att fortsätta. Detta är en oväntad bugg som kan rapporteras enligt nedan beskrivning.</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Ett allvarligt fel skedde. Se att filen för inställningar är möjlig att skriva, eller försök köra med "-nosettings"</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">Fel: Angiven datakatalog "%1" finns inte.</translation>
</message>
@@ -260,6 +274,10 @@ Försök igen.</translation>
<translation type="unfinished">Fel: %1</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 har inte avslutats korrekt än...</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation type="unfinished">okänd</translation>
</message>
@@ -348,6 +366,14 @@ Försök igen.</translation>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Filen för inställningar kunde inte läsas</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Filen för inställningar kunde inte skapas</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">%s-utvecklarna</translation>
</message>
@@ -372,10 +398,6 @@ Försök igen.</translation>
<translation type="unfinished">Fel vid läsning av %s! Alla nycklar lästes korrekt, men transaktionsdata eller poster i adressboken kanske saknas eller är felaktiga.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Fel: Avlyssning av inkommande anslutningar misslyckades (Avlyssningen returnerade felkod %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Avgiftsuppskattning misslyckades. Fallbackfee är inaktiverat. Vänta några block eller aktivera -fallbackfee.</translation>
</message>
@@ -540,10 +562,6 @@ Försök igen.</translation>
<translation type="unfinished">Fel vid läsning från databas, avslutar.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Fel vid uppgradering av blockdatabasen</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">Fel: Diskutrymme är lågt för %s</translation>
</message>
@@ -624,16 +642,28 @@ Försök igen.</translation>
<translation type="unfinished">Laddar P2P-adresser…</translation>
</message>
<message>
+ <source>Loading banlist…</source>
+ <translation type="unfinished">Läser in listan över bannlysningar …</translation>
+ </message>
+ <message>
+ <source>Loading block index…</source>
+ <translation type="unfinished">Läser in blockindex...</translation>
+ </message>
+ <message>
<source>Loading wallet…</source>
<translation type="unfinished">Laddar plånboken…</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">Saknat belopp</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">Port måste anges med -whitelist: '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Ingen proxy-server vald. Använd -proxy=&lt;ip&gt; eller -proxy=&lt;ip:port&gt;.</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Inga adresser tillgängliga</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -648,6 +678,10 @@ Försök igen.</translation>
<translation type="unfinished">Gallringsläge är inkompatibelt med -txindex.</translation>
</message>
<message>
+ <source>Pruning blockstore…</source>
+ <translation type="unfinished">Rensar blockstore...</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation type="unfinished">Minskar -maxconnections från %d till %d, på grund av systembegränsningar.</translation>
</message>
@@ -764,6 +798,10 @@ Försök igen.</translation>
<translation type="unfinished">Det gick inte att skapa nycklar</translation>
</message>
<message>
+ <source>Unable to open %s for writing</source>
+ <translation type="unfinished">Det går inte att öppna %s för skrivning</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">Kunde inte starta HTTP-server. Se felsökningsloggen för detaljer.</translation>
</message>
@@ -788,10 +826,6 @@ Försök igen.</translation>
<translation type="unfinished">Saknar stöd för loggningskategori %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">Uppgraderar UTXO-databasen</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Kommentaren i användaragent (%s) innehåller osäkra tecken.</translation>
</message>
@@ -859,6 +893,10 @@ Försök igen.</translation>
<translation type="unfinished">Skapa ny plånbok</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Minimera</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">Plånbok:</translation>
</message>
@@ -904,6 +942,10 @@ Försök igen.</translation>
<translation type="unfinished">Kryptera de privata nycklar som tillhör din plånbok</translation>
</message>
<message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;Säkerhetskopiera plånbok...</translation>
+ </message>
+ <message>
<source>&amp;Change Passphrase…</source>
<translation type="unfinished">&amp;Ändra lösenordsfras…</translation>
</message>
@@ -960,10 +1002,30 @@ Försök igen.</translation>
<translation type="unfinished">Verktygsfält för flikar</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Synkar huvuden (%1%)...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Synkroniserar med nätverket...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Indexerar block på disken...</translation>
+ </message>
+ <message>
<source>Processing blocks on disk…</source>
<translation type="unfinished">Behandlar block på disken…</translation>
</message>
<message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Indexerar om block på disken...</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">Ansluter till noder...</translation>
+ </message>
+ <message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished">Begär betalningar (skapar QR-koder och bitcoin: -URIer)</translation>
</message>
@@ -1019,6 +1081,10 @@ Försök igen.</translation>
<translation type="unfinished">Läs in Delvis signerad Bitcoin transaktion (PSBT)</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">Ladda PSBT från &amp;urklipp...</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Läs in Delvis signerad Bitcoin transaktion (PSBT) från urklipp</translation>
</message>
@@ -1055,6 +1121,16 @@ Försök igen.</translation>
<translation type="unfinished">Stäng plånboken</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Återställ Plånboken...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Återställt en plånbok från en backup-fil</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Stäng alla plånböcker</translation>
</message>
@@ -1079,6 +1155,21 @@ Försök igen.</translation>
<translation type="unfinished">Inga plånböcker tillgängliga</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Plånboksdata</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Återställ Plånbok</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Namn på plånboken</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Fönster</translation>
</message>
@@ -1094,6 +1185,10 @@ Försök igen.</translation>
<source>%1 client</source>
<translation type="unfinished">%1-klient</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">och göm</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -1103,11 +1198,21 @@ Försök igen.</translation>
</translation>
</message>
<message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Klicka för fler alternativ</translation>
+ </message>
+ <message>
<source>Disable network activity</source>
<extracomment>A context menu item.</extracomment>
<translation type="unfinished">Stäng av nätverksaktivitet</translation>
</message>
<message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">Aktivera nätverksaktivitet</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Fel: %1</translation>
</message>
@@ -1358,6 +1463,19 @@ Försök igen.</translation>
<source>Can't list signers</source>
<translation type="unfinished">Kan inte lista signerare</translation>
</message>
+ </context>
+<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">Ladda plånböcker</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">Laddar plånböcker…</translation>
+ </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1378,6 +1496,29 @@ Försök igen.</translation>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">Öppna plånbok</translation>
</message>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">Öppnar Plånboken &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
+<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Återställ Plånbok</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Återskapar Plånboken &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Det gick inte att återställa plånboken</translation>
+ </message>
</context>
<context>
<name>WalletController</name>
@@ -1529,9 +1670,26 @@ Försök igen.</translation>
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(av %1 GB krävs)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1578,8 +1736,8 @@ Försök igen.</translation>
<translation type="unfinished">Eftersom detta är första gången som programmet startas får du välja var %1 skall lagra sina data.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">När du trycker OK kommer %1 att börja ladda ner och bearbeta den fullständiga %4-blockkedjan (%2 GB), med början vid de första transaktionerna %3 när %4 först lanserades.</translation>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">Begränsa lagringsplats för blockkedjan till </translation>
</message>
<message>
<source>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>
@@ -1758,10 +1916,20 @@ Försök igen.</translation>
<translation type="unfinished">(0 = auto, &lt;0 = lämna så många kärnor lediga)</translation>
</message>
<message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">Aktivera R&amp;PC-server</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">&amp;Plånbok</translation>
</message>
<message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Ta bort avgift från summa som standard</translation>
+ </message>
+ <message>
<source>Enable coin &amp;control features</source>
<translation type="unfinished">Aktivera mynt&amp;kontrollfunktioner</translation>
</message>
@@ -1774,6 +1942,11 @@ Försök igen.</translation>
<translation type="unfinished">&amp;Spendera obekräftad växel</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Aktivera &amp;PSBT-kontroll</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">Öppna automatiskt Bitcoin-klientens port på routern. Detta fungerar endast om din router stödjer UPnP och det är är aktiverat.</translation>
</message>
@@ -1782,6 +1955,10 @@ Försök igen.</translation>
<translation type="unfinished">Tilldela port med hjälp av &amp;UPnP</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Öppna automatiskt Bitcoin-klientens port på routern. Detta fungerar endast om din router stödjer NAT-PMP och det är är aktiverat. Den externa porten kan vara slumpmässig.</translation>
+ </message>
+ <message>
<source>Accept connections from outside.</source>
<translation type="unfinished">Acceptera anslutningar utifrån.</translation>
</message>
@@ -1858,10 +2035,6 @@ Försök igen.</translation>
<translation type="unfinished">Anslut till Bitcoin-nätverket genom en separat SOCKS5-proxy för onion-tjänster genom Tor.</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Alternativ som anges i denna dialog åsidosätts av kommandoraden eller i konfigurationsfilen:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;Avbryt</translation>
</message>
@@ -1875,14 +2048,17 @@ Försök igen.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Bekräfta att alternativen ska återställs</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Klientomstart är nödvändig för att aktivera ändringarna.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Programmet kommer att stängas. Vill du fortsätta?</translation>
</message>
<message>
@@ -1896,6 +2072,10 @@ Försök igen.</translation>
<translation type="unfinished">Konfigurationsfilen används för att ange avancerade användaralternativ som åsidosätter inställningar i GUI. Dessutom kommer alla kommandoradsalternativ att åsidosätta denna konfigurationsfil.</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">Fortsätt</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">Avbryt</translation>
</message>
@@ -2034,6 +2214,10 @@ Försök igen.</translation>
<translation type="unfinished">Ett fel uppstod när transaktionen behandlades.</translation>
</message>
<message>
+ <source>PSBT copied to clipboard.</source>
+ <translation type="unfinished">PSBT kopierad till urklipp.</translation>
+ </message>
+ <message>
<source>Save Transaction Data</source>
<translation type="unfinished">Spara transaktionsdetaljer</translation>
</message>
@@ -2121,6 +2305,11 @@ Försök igen.</translation>
<translation type="unfinished">Användaragent</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Ã…lder</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Riktning</translation>
@@ -2300,6 +2489,10 @@ Försök igen.</translation>
<translation type="unfinished">Synkade block</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Senaste Transaktion</translation>
+ </message>
+ <message>
<source>Mapped AS</source>
<translation type="unfinished">Kartlagd AS</translation>
</message>
@@ -2572,6 +2765,10 @@ Försök igen.</translation>
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>Request payment to …</source>
+ <translation type="unfinished">Begär betalning till ...</translation>
+ </message>
+ <message>
<source>Address:</source>
<translation type="unfinished">Adress</translation>
</message>
@@ -2911,10 +3108,6 @@ Försök igen.</translation>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">En avgift högre än %1 anses vara en absurd hög avgift.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Betalningsbegäran löpte ut.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2994,14 +3187,6 @@ Försök igen.</translation>
<translation type="unfinished">Meddelande:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Detta är en oautentiserad betalningsbegäran.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Detta är en autentiserad betalningsbegäran.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Ange en etikett för denna adress för att lägga till den i listan med använda adresser</translation>
</message>
@@ -3009,14 +3194,6 @@ Försök igen.</translation>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Ett meddelande som bifogades bitcoin: -URIn och som sparas med transaktionen som referens. Obs: Meddelandet sänds inte över Bitcoin-nätverket.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Betala till:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">PM:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3183,30 +3360,22 @@ Försök igen.</translation>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">konflikt med en transaktion med %1 bekräftelser</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/obekräftade, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">i minnespoolen</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ej i minnespoolen</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">övergiven</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/obekräftade</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 bekräftelser</translation>
</message>
<message>
@@ -3689,6 +3858,11 @@ Gå till Fil &gt; Öppna plånbok för att läsa in en plånbok.
<translation type="unfinished">Säkerhetskopiera Plånbok</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Plånboksdata</translation>
+ </message>
+ <message>
<source>Backup Failed</source>
<translation type="unfinished">Säkerhetskopiering misslyckades</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sw.ts b/src/qt/locale/bitcoin_sw.ts
index e0adc1e10d..d4e26bb765 100644
--- a/src/qt/locale/bitcoin_sw.ts
+++ b/src/qt/locale/bitcoin_sw.ts
@@ -115,6 +115,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_szl.ts b/src/qt/locale/bitcoin_szl.ts
index b3375bb9b4..6c59c4cb80 100644
--- a/src/qt/locale/bitcoin_szl.ts
+++ b/src/qt/locale/bitcoin_szl.ts
@@ -802,6 +802,24 @@
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Co nojmynij %1 GB datÅw ôstanie spamiyntane w tym katalogu, daty te bydÅm z czasym corÅz srogsze.</translation>
@@ -846,10 +864,6 @@
<translation type="unfinished">PÅniywÅż je to piyrsze sztartniyÅ„cie programu, możesz ôbrać kaj %1 bydzie spamiyntować swoje daty.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Kej naciÅ›niesz OK, %1 zacznie pobiyrać i przetwÅrzać coÅ‚kõ %4 keta blokÅw (%2GB) przi zaczynaniu ôd piyrszych transakcyji w %3 kej %4 ôstoÅ‚ sztartniynty.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">WstympnÅ synchrÅnizacyjÅ je barzo wymÅgajÅncÅ i może wyzdradzić wczaÅ›nij niyzaôbserwowane niyprzileżytoÅ›ci sprzyntowe. Za kożdym sztartniyÅ„ciym %1 sebiyranie bydzie kÅntynuowane ôd placu w kerym ôstaÅ‚o zastawiÅne.</translation>
</message>
@@ -1498,7 +1512,7 @@
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">WiadÅmość, kerŠôstaÅ‚a prziwstÅnÅ do URI bitcoin:, kerÅ bydzie przechowowanÅ z transakcyjÅm w cylach informacyjnych. NapÅmniynie: Ta wiadÅmość niy bydzie rozszyrzowanÅ w necu Bitcoin.</translation>
</message>
- </context>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
<message>
diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts
index 85b7bb4691..ab36f4a85c 100644
--- a/src/qt/locale/bitcoin_ta.ts
+++ b/src/qt/locale/bitcoin_ta.ts
@@ -92,6 +92,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">à®®à¯à®•à®µà®°à®¿ படà¯à®Ÿà®¿à®¯à®²à¯ à®à®•à¯à®¸à¯à®ªà¯‹à®°à¯à®Ÿà¯ செயà¯à®•Â </translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">கமா பிரிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ கோபà¯à®ªà¯</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">à®®à¯à®•à®µà®°à®¿ படà¯à®Ÿà®¿à®¯à®²à¯ˆ %1 கà¯à®•à¯ சேமிகà¯à®• à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à¯à®®à¯ ஒர௠பிழை à®à®±à¯à®ªà®Ÿà¯à®Ÿà®¤à¯. தயவà¯à®šà¯†à®¯à¯à®¤à¯ மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®µà¯à®®à¯.</translation>
@@ -235,6 +240,21 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">ரனவே எகà¯à®¸à¯†à®ªà¯à®·à®©à¯</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">ஒர௠அபாயகரமான à®à®°à®±à¯ à®à®±à¯à®ªà®Ÿà¯à®Ÿà®¤à¯. %1 இனி பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®• தொடர à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯ மறà¯à®±à¯à®®à¯ வெளியேறà¯à®®à¯</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">உள௠எறரà¯</translation>
+ </message>
+ </context>
+<context>
<name>QObject</name>
<message>
<source>Error: Specified data directory "%1" does not exist.</source>
@@ -249,6 +269,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">பிழை: %1</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1இனà¯à®©à¯à®®à¯ பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®• வெளியேரவிலà¯à®²à¯ˆ ...</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation type="unfinished">தெரியாத</translation>
</message>
@@ -400,6 +424,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">தீரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯ -%s à®®à¯à®•à®µà®°à®¿: '%s'</translation>
</message>
<message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation type="unfinished">-blockfiltersindex இலà¯à®²à®¾à®¤ -peerblockfilters அமைபà¯à®ªà¯ à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯ </translation>
+ </message>
+ <message>
<source>Copyright (C) %i-%i</source>
<translation type="unfinished">பதிபà¯à®ªà¯à®°à®¿à®®à¯ˆ (ப) %i-%i</translation>
</message>
@@ -452,10 +480,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">டேடà¯à®Ÿà®¾à®ªà¯‡à®šà®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ படிபà¯à®ªà®¤à®¿à®²à¯ பிழை, ஷட௠டவà¯à®©à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">செயினà¯à®¸à¯à®Ÿà¯‡à®Ÿà¯ தகவலà¯à®¤à®³à®¤à¯à®¤à¯ˆ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®µà®¤à®¿à®²à¯ பிழை</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">பிழை: டிஸà¯à®•à¯ ஸà¯à®ªà¯‡à®¸à¯ %s கà¯à®•à¯ கà¯à®±à¯ˆà®µà®¾à®• உளà¯à®³à®¤à¯</translation>
</message>
@@ -596,10 +620,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">தெரியாத மாறà¯à®±à¯ வகை '%s'</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">UTXO தகவலà¯à®¤à®³à®®à¯ மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯</translation>
- </message>
- <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation type="unfinished">வாலட௠மீணà¯à®Ÿà¯à®®à¯ எழà¯à®¤ படவேணà¯à®Ÿà¯à®®à¯: à®®à¯à®Ÿà®¿à®•à¯à®• %s ஠மறà¯à®¤à¯Šà®Ÿà®•à¯à®•à®®à¯ செயà¯à®¯à¯à®™à¯à®•à®³à¯</translation>
</message>
@@ -655,6 +675,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">பà¯à®¤à®¿à®¯ வாலடà¯à®Ÿà¯ˆ உரà¯à®µà®¾à®•à¯à®•à¯</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;கà¯à®±à¯ˆà®¤à¯à®¤à®²à¯</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">கைபà¯à®ªà¯ˆ:</translation>
</message>
@@ -692,6 +716,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">உஙà¯à®•à®³à¯ பணபà¯à®ªà¯ˆà®šà¯ சேரà¯à®¨à¯à®¤ தனிபà¯à®ªà®Ÿà¯à®Ÿ விசைகளை கà¯à®±à®¿à®¯à®¾à®•à¯à®•à¯à®•</translation>
</message>
<message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;பேகà¯à®•à®ªà¯ வாலடà¯...</translation>
+ </message>
+ <message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
<translation type="unfinished">உஙà¯à®•à®³à¯ பிடà¯à®Ÿà®¿à®©à®¿à®©à¯ à®®à¯à®•à®µà®°à®¿à®¯à¯à®Ÿà®©à¯ செயà¯à®¤à®¿à®•à®³à¯ˆ உஙà¯à®•à®³à®¿à®Ÿà®®à¯ வைதà¯à®¤à®¿à®°à¯à®ªà¯à®ªà®¤à¯ˆ நிரூபிகà¯à®•</translation>
</message>
@@ -700,6 +728,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿ விகà¯à®•à®¿à®ªà¯€à®Ÿà®¿à®¯à®¾ à®®à¯à®•à®µà®°à¯à®•à®³à¯à®Ÿà®©à¯ கையொபà¯à®ªà®®à®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ˆ உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤, செயà¯à®¤à®¿à®•à®³à¯ˆ சரிபாரà¯à®•à¯à®•à®µà¯à®®à¯</translation>
</message>
<message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">திறநà¯à®¤ &amp;யூஆறà¯à®...</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation type="unfinished">&amp;கோபà¯à®ªà¯</translation>
</message>
@@ -828,6 +860,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">வாலட௠எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">வாலட௠பெயரà¯</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;சாளரமà¯</translation>
</message>
@@ -1244,6 +1281,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">கà¯à®±à¯ˆà®¨à¯à®¤à®¤à¯ %1 ஜிபி தரவ௠இநà¯à®¤ அடைவில௠சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯, மேலà¯à®®à¯ காலபà¯à®ªà¯‹à®•à¯à®•à®¿à®²à¯ அத௠வளரà¯à®®à¯.</translation>
@@ -1289,10 +1347,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">இத௠மà¯à®¤à®²à¯ à®®à¯à®±à¯ˆà®¯à®¾à®• தà¯à®µà®™à¯à®•à®¿à®¯à®¤à¯, நீஙà¯à®•à®³à¯ %1 அதன௠தரவை எஙà¯à®•à¯ சேமிதà¯à®¤à¯ வைகà¯à®•à¯à®®à¯ எனà¯à®ªà®¤à¯ˆ தேரà¯à®µà¯ செயà¯à®¯à®²à®¾à®®à¯.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">நீஙà¯à®•à®³à¯ சரி எனà¯à®ªà®¤à¯ˆà®•à¯ கிளிக௠செயà¯à®¤à®¾à®²à¯ %1 ஆரமà¯à®ªà®¤à¯à®¤à®¿à®²à¯ %4 இல௠ஆரமà¯à®ªà®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ %3 இன௠ஆரமà¯à®ª பரிவரà¯à®¤à¯à®¤à®©à¯ˆà®•à®³à¯ˆà®¤à¯ தொடஙà¯à®•à¯à®®à¯ போத௠மà¯à®´à¯ %4 தொகà¯à®¤à®¿ சஙà¯à®•à®¿à®²à®¿ (%2GB) பதிவிறகà¯à®• மறà¯à®±à¯à®®à¯ செயலாகà¯à®•à®¤à¯ தொடஙà¯à®•à¯à®®à¯.</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">இநà¯à®¤ அமைபà¯à®ªà¯ˆ மாறà¯à®±à®¿à®¯à®®à¯ˆà®•à¯à®• à®®à¯à®´à¯ பிளாகà¯à®šà¯†à®¯à®¿à®©à¯ˆà®¯à¯à®®à¯ மீணà¯à®Ÿà¯à®®à¯ டவà¯à®©à¯à®²à¯‹à®Ÿà¯ செயà¯à®¯ வேணà¯à®Ÿà¯à®®à¯. à®®à¯à®¤à®²à®¿à®²à¯ à®®à¯à®´à¯ செயினையà¯à®®à¯ டவà¯à®©à¯à®²à¯‹à®Ÿà¯ செயà¯à®¤ பினà¯à®©à®°à¯ பà¯à®°à¯‚ன௠செயà¯à®µà®¤à¯ வேகமான செயல௠ஆகà¯à®®à¯. சில மேமà¯à®ªà®Ÿà¯à®Ÿ à®…à®®à¯à®šà®™à¯à®•à®³à¯ˆ à®®à¯à®Ÿà®•à¯à®•à¯à®®à¯.</translation>
</message>
@@ -1565,10 +1619,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">நாணயக௠கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ à®…à®®à¯à®šà®™à¯à®•à®³à¯ˆà®•à¯ காடà¯à®Ÿà®²à®¾à®®à®¾ அலà¯à®²à®¤à¯ இலà¯à®²à¯ˆà®¯à®¾.</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">இநà¯à®¤ உரையாடலில௠அமைகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³ விரà¯à®ªà¯à®ªà®™à¯à®•à®³à¯ கடà¯à®Ÿà®³à¯ˆ வரியில௠அலà¯à®²à®¤à¯ கடà¯à®Ÿà®®à¯ˆà®ªà¯à®ªà¯ கோபà¯à®ªà®¿à®²à¯ மீளமைகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">&amp;சரி</translation>
</message>
@@ -1582,14 +1632,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">விரà¯à®ªà¯à®ªà®™à¯à®•à®³à¯ˆ மீடà¯à®Ÿà®®à¯ˆà®•à¯à®•à®µà¯à®®à¯</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">மாறà¯à®±à®™à¯à®•à®³à¯ˆà®šà¯ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤ கிளையன௠மறà¯à®¤à¯Šà®Ÿà®•à¯à®•à®®à¯ தேவை.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">கிளையணà¯à®Ÿà¯ மூடபà¯à®ªà®Ÿà¯à®®à¯. நீஙà¯à®•à®³à¯ தொடர விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?</translation>
</message>
<message>
@@ -1697,6 +1750,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>PSBTOperationsDialog</name>
<message>
+ <source>Sign Tx</source>
+ <translation type="unfinished">கையெழà¯à®¤à¯à®¤à¯ Tx</translation>
+ </message>
+ <message>
<source>Close</source>
<translation type="unfinished">நெரà¯à®•à¯à®•à®®à®¾à®©</translation>
</message>
@@ -2419,10 +2476,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Transaction creation failed!</source>
<translation type="unfinished">பரிவரà¯à®¤à¯à®¤à®©à¯ˆ உரà¯à®µà®¾à®•à¯à®•à®®à¯ தோலà¯à®µà®¿à®¯à®Ÿà¯ˆà®¨à¯à®¤à®¤à¯!</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">கடà¯à®Ÿà®£à®®à¯ கோரிகà¯à®•à¯ˆ காலாவதியானதà¯.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2498,14 +2551,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">செயà¯à®¤à®¿:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">இத௠ஒர௠அஙà¯à®•à¯€à®•à®°à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà®¾à®¤ கடà¯à®Ÿà®£ கோரிகà¯à®•à¯ˆ.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">இத௠ஒர௠அஙà¯à®•à¯€à®•à®°à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ கடà¯à®Ÿà®£ கோரிகà¯à®•à¯ˆ.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">இநà¯à®¤ à®®à¯à®•à®µà®°à®¿à®¯à¯ˆ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿ à®®à¯à®•à®µà®°à®¿à®•à®³à®¿à®©à¯ படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ சேரà¯à®•à¯à®• ஒர௠லேபிளை உளà¯à®³à®¿à®Ÿà®µà¯à®®à¯.</translation>
</message>
@@ -2513,14 +2558,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">பிடà¯à®•à®¾à®¯à®¿à®©à¯à®Ÿà®©à¯ இணைகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ செயà¯à®¤à®¿: உஙà¯à®•à®³à¯ எதிரà¯à®•à®¾à®² கà¯à®±à®¿à®ªà¯à®ªà¯à®•à¯à®•à®¾à®• பரிவரà¯à®¤à¯à®¤à®©à¯ˆà®¯à¯à®Ÿà®©à¯ யூஆரà¯à® சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯. கà¯à®±à®¿à®ªà¯à®ªà¯: இநà¯à®¤ செயà¯à®¤à®¿ பிடà¯à®•à®¾à®¯à®¿à®©à¯ வலையமைபà¯à®ªà®¿à®±à¯à®•à¯ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà®¾à®¤à¯.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">பணம௠செலà¯à®¤à¯à®¤à¯:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">கà¯à®±à®¿à®ªà¯à®ªà®¾à®£à¯ˆ:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -2665,33 +2702,32 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>SplashScreen</name>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">ஷடà¯à®Ÿà®µà¯à®©à¯ செயà¯à®¯, "q" à® à®…à®´à¯à®¤à¯à®¤à®µà¯à®®à¯</translation>
+ </message>
+</context>
+<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">%1 உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯à®•à®³à¯à®Ÿà®©à¯ ஒர௠பரிவரà¯à®¤à¯à®¤à®©à¯ˆ à®®à¯à®°à®£à¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà®¾à®¤à®¤à¯, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">மெமரி பூலில௠உளà¯à®³à®¤à¯</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">மெமரி பூலில௠இலà¯à®²à¯ˆ</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">கைவிடபà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà®¾à®¤à®¤à¯</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯</translation>
</message>
<message>
@@ -2983,6 +3019,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">பரிவரà¯à®¤à¯à®¤à®©à¯ˆà®¯à®¿à®©à¯ வரலாறà¯à®±à¯ˆ எகà¯à®¸à¯à®ªà¯‹à®°à¯à®Ÿà¯ செயà¯</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">கமா பிரிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ கோபà¯à®ªà¯</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">உறà¯à®¤à®¿à®¯à®¾à®•</translation>
</message>
diff --git a/src/qt/locale/bitcoin_te.ts b/src/qt/locale/bitcoin_te.ts
index 38e49ee98a..4044f341ac 100644
--- a/src/qt/locale/bitcoin_te.ts
+++ b/src/qt/locale/bitcoin_te.ts
@@ -429,6 +429,27 @@
<translation type="unfinished">బిటà±à°•à±‹à°¯à°¿à°¨à±</translation>
</message>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_th.ts b/src/qt/locale/bitcoin_th.ts
index 1d7c403a4c..44052c6b24 100644
--- a/src/qt/locale/bitcoin_th.ts
+++ b/src/qt/locale/bitcoin_th.ts
@@ -3,11 +3,11 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">คลิà¸à¸‚วาเพื่อà¹à¸à¹‰à¹„ขที่อยู่หรือป้ายชื่อ</translation>
+ <translation type="unfinished">คลิà¸à¸‚วา เพื่อ à¹à¸à¹‰à¹„ข à¹à¸­à¸”เดรส หรือ เลเบล</translation>
</message>
<message>
<source>Create a new address</source>
- <translation type="unfinished">สร้างที่อยู่ใหม่</translation>
+ <translation type="unfinished">สร้าง à¹à¸­à¸”เดรส ใหม่</translation>
</message>
<message>
<source>&amp;New</source>
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation type="unfinished">คัดลอà¸à¸—ี่อยู่ที่เลือà¸à¹ƒà¸™à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™à¹„ปยังคลิปบอร์ดของระบบ</translation>
+ <translation type="unfinished">คัดลอภà¹à¸­à¸”เดรส ที่เลือภในปัจจุบัน ไปยัง คลิปบอร์ด ของระบบ</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -27,11 +27,11 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished">ลบที่อยู่ที่เลือà¸à¹ƒà¸™à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™à¸­à¸­à¸à¸ˆà¸²à¸à¸£à¸²à¸¢à¸à¸²à¸£</translation>
+ <translation type="unfinished">ลบà¹à¸­à¸”เดรสที่เลือà¸à¹ƒà¸™à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™à¸­à¸­à¸à¸ˆà¸²à¸à¸£à¸²à¸¢à¸à¸²à¸£</translation>
</message>
<message>
<source>Enter address or label to search</source>
- <translation type="unfinished">ป้อนที่อยู่หรือป้ายชื่อเพื่อค้นหา</translation>
+ <translation type="unfinished">ป้อน à¹à¸­à¸”เดรส หรือ เลเบล เพื่อ ทำà¸à¸²à¸£à¸„้นหา</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
@@ -47,11 +47,11 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation type="unfinished">เลือà¸à¸—ี่อยู่ที่จะส่งเหรียà¸</translation>
+ <translation type="unfinished">เลือภà¹à¸­à¸”เดรส ที่จะ ส่ง คอยน์ ไป</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation type="unfinished">เลือà¸à¸—ี่อยู่ที่จะรับเหรียà¸</translation>
+ <translation type="unfinished">เลือภà¹à¸­à¸”เดรส ที่จะ รับ คอยน์</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -59,19 +59,29 @@
</message>
<message>
<source>Sending addresses</source>
- <translation type="unfinished">ที่อยู่à¸à¸²à¸£à¸ªà¹ˆà¸‡</translation>
+ <translation type="unfinished">à¹à¸­à¸”เดรส à¸à¸²à¸£à¸ªà¹ˆà¸‡</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation type="unfinished">ที่อยู่à¸à¸²à¸£à¸£à¸±à¸š</translation>
+ <translation type="unfinished">à¹à¸­à¸”เดรส à¸à¸²à¸£à¸£à¸±à¸š</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation type="unfinished">&amp;คัดลอà¸à¸—ี่อยู่</translation>
+ <translation type="unfinished">&amp;คัดลอภà¹à¸­à¸”เดรส</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation type="unfinished">&amp;คัดลอà¸à¸›à¹‰à¸²à¸¢à¸Šà¸·à¹ˆà¸­</translation>
+ <translation type="unfinished">คัดลอภ&amp;เลเบล</translation>
</message>
<message>
<source>&amp;Edit</source>
@@ -79,12 +89,17 @@
</message>
<message>
<source>Export Address List</source>
- <translation type="unfinished">ส่งออà¸à¸£à¸²à¸¢à¸à¸²à¸£à¸—ี่อยู่</translation>
+ <translation type="unfinished">ส่งออà¸à¸£à¸²à¸¢à¸à¸²à¸£à¹à¸­à¸”เดรส</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">เครื่องหมายจุลภาค (Comma) เพื่อà¹à¸¢à¸à¹„ฟล์</translation>
</message>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
- <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาดขณะพยายามบันทึà¸à¸£à¸²à¸¢à¸à¸²à¸£à¸—ี่อยู่ไปยัง %1 โปรดลองอีà¸à¸„รั้ง</translation>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาดขณะพยายามบันทึà¸à¸£à¸²à¸¢à¸à¸²à¸£à¹à¸­à¸”เดรสไปยัง %1 โปรดลองอีà¸à¸„รั้ง</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -95,92 +110,140 @@
<name>AddressTableModel</name>
<message>
<source>Label</source>
- <translation type="unfinished">ป้ายชื่อ</translation>
+ <translation type="unfinished">เลเบล</translation>
</message>
<message>
<source>Address</source>
- <translation type="unfinished">ที่อยู่</translation>
+ <translation type="unfinished">à¹à¸­à¸”เดรส</translation>
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ไม่มีป้ายชื่อ)</translation>
+ <translation type="unfinished">(ไม่มีเลเบล)</translation>
</message>
</context>
<context>
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
- <translation type="unfinished">à¸à¸¥à¹ˆà¸­à¸‡à¹‚ต้ตอบวลีรหัสผ่าน</translation>
+ <translation type="unfinished">พาสเฟส ไดอะล็อà¸</translation>
</message>
<message>
<source>Enter passphrase</source>
- <translation type="unfinished">ป้อนวลีรหัสผ่าน</translation>
+ <translation type="unfinished">ป้อน พาสเฟส</translation>
</message>
<message>
<source>New passphrase</source>
- <translation type="unfinished">วลีรหัสผ่านใหม่</translation>
+ <translation type="unfinished">พาสดฟสใหม่</translation>
</message>
<message>
<source>Repeat new passphrase</source>
- <translation type="unfinished">ทำซ้ำวลีรหัสผ่านใหม่</translation>
+ <translation type="unfinished">ทำซ้ำ พาสเฟส ใหม่</translation>
</message>
<message>
<source>Show passphrase</source>
- <translation type="unfinished">à¹à¸ªà¸”งวลีรหัสผ่าน</translation>
+ <translation type="unfinished">à¹à¸ªà¸”งพาสเฟส</translation>
</message>
<message>
<source>Encrypt wallet</source>
- <translation type="unfinished">เข้ารหัสà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">เข้ารหัสวอลเล็ต</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£ นี้ ต้องà¸à¸²à¸£ วอลเล็ต พาสเฟส ของ คุณ เพื่อ ปลดล็อค วอลเล็ต</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation type="unfinished">ปลดล็อคà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">ปลดล็อควอลเล็ต</translation>
</message>
<message>
<source>Change passphrase</source>
- <translation type="unfinished">เปลี่ยนวลีรหัสผ่าน</translation>
+ <translation type="unfinished">เปลี่ยนพาสเฟส</translation>
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation type="unfinished">ยืนยันà¸à¸²à¸£à¹€à¸‚้ารหัสà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">ยืนยันà¸à¸²à¸£à¹€à¸‚้ารหัสวอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation type="unfinished">คำเตือน: หาภคุณ เข้ารหัส วอลเล็ต ของคุณ à¹à¸¥à¸° ทำพาสเฟส หาย , คุณ จะ สูà¸à¹€à¸ªà¸µà¸¢ &lt;b&gt;BITCOINS ทั้งหมดของคุณ&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation type="unfinished">คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¸«à¸£à¸·à¸­à¹„ม่ว่าต้องà¸à¸²à¸£à¹€à¸‚้ารหัสà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ของคุณ?</translation>
+ <translation type="unfinished">คุณ à¹à¸™à¹ˆà¹ƒà¸ˆ หรือไม่ว่า ต้องà¸à¸²à¸£ เข้ารหัส วอลเล็ต ของคุณ?</translation>
</message>
<message>
<source>Wallet encrypted</source>
- <translation type="unfinished">เข้ารหัสบัà¸à¸Šà¸µà¹€à¸£à¸µà¸¢à¸šà¸£à¹‰à¸­à¸¢</translation>
+ <translation type="unfinished">เข้ารหัสวอลเล็ตเรียบร้อย</translation>
+ </message>
+ <message>
+ <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">ป้อน พาสเฟส ใหม่ สำหรับ วอลเล็ต&lt;br/&gt;à¸à¸£à¸¸à¸“า ใช้ พาสเฟส ของ &lt;b&gt;สิบ หรือ อัà¸à¸‚ระ สุ่ม สิบ ตัว ขึ้นไป &lt;/b&gt;, หรือ &lt;b&gt;à¹à¸›à¸” หรือ à¹à¸›à¸”คำขึ้นไป&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation type="unfinished">ป้อนพาสเฟสเà¸à¹ˆà¸²à¹à¸¥à¸°à¸žà¸²à¸ªà¹€à¸Ÿà¸ªà¹ƒà¸«à¸¡à¹ˆà¸ªà¸³à¸«à¸£à¸±à¸šà¸§à¸­à¸¥à¹€à¸¥à¹‡à¸•</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation type="unfinished">โปรดจำ ไว้ว่า à¸à¸²à¸£à¹€à¸‚้ารหัส วอลเล็ต ของคุณ ไม่สามารถ ปà¸à¸›à¹‰à¸­à¸‡ bitcoins ของคุณ ได้อย่างเต็มที่ จาà¸à¸à¸²à¸£ ถูà¸à¸‚โมย โดยมัลà¹à¸§à¸£à¹Œ ที่ติดไวรัส บนคอมพิวเตอร์ ของคุณ</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation type="unfinished">วอลเล็ตที่จะเข้ารหัส</translation>
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation type="unfinished">บัà¸à¸Šà¸µà¸‚องคุณà¸à¸³à¸¥à¸±à¸‡à¸–ูà¸à¹€à¸‚้ารหัส</translation>
+ <translation type="unfinished">วอลเล็ตของคุณà¸à¸³à¸¥à¸±à¸‡à¸–ูà¸à¹€à¸‚้ารหัส</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation type="unfinished">บัà¸à¸Šà¸µà¸‚องคุณถูà¸à¹€à¸‚้ารหัสเรียบร้อยà¹à¸¥à¹‰à¸§</translation>
+ <translation type="unfinished">วอลเล็ตของคุณถูà¸à¹€à¸‚้ารหัสเรียบร้อยà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation type="unfinished">สำคัà¸: à¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูลใด ๆ à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²à¸™à¸µà¹‰à¸—ี่คุณได้ทำขึ้นจาà¸à¹„ฟล์วอลเล็ตของคุณควรถูà¸à¹à¸—นที่ด้วยไฟล์วอลเล็ตที่เข้ารหัสที่สร้างขึ้นใหม่ ด้วยเหตุผลด้านความปลอดภัย à¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูลà¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²à¸‚องไฟล์วอลเล็ตที่ไม่ได้เข้ารหัสจะไม่มีประโยชน์ทันทีที่คุณเริ่มใช้วอลเล็ตใหม่ที่เข้ารหัส</translation>
</message>
<message>
<source>Wallet encryption failed</source>
- <translation type="unfinished">à¸à¸²à¸£à¹€à¸‚้ารหัสà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ล้มเหลว</translation>
+ <translation type="unfinished">à¸à¸²à¸£à¹€à¸‚้ารหัสวอลเล็ตล้มเหลว</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation type="unfinished">à¸à¸²à¸£à¹€à¸‚้ารหัส วอลเลต ล้มเหลว เนื่องจาภข้อผิดพลาด ภายใน วอลเล็ต ของคุณ ไม่ได้ เข้ารหัส</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">พาสเฟสที่ป้อนไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
</message>
<message>
<source>Wallet unlock failed</source>
- <translation type="unfinished">à¸à¸²à¸£à¸›à¸¥à¸”ล็อคà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ล้มเหลว</translation>
+ <translation type="unfinished">à¸à¸²à¸£à¸›à¸¥à¸”ล็อควอลเล็ตล้มเหลว</translation>
</message>
- </context>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation type="unfinished">พาสเฟส ที่ป้อน สำหรับ à¸à¸²à¸£à¸–อดรหัส วอลเล็ต ไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished">เปลี่ยนพาสเฟสวอลเล็ตสำเร็จà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished">คำเตือน:à¹à¸›à¹‰à¸™à¸„ีย์ตัวอัà¸à¸©à¸£à¸žà¸´à¸¡à¸žà¹Œà¹ƒà¸«à¸à¹ˆ (Cap Lock) ถูà¸à¹€à¸›à¸´à¸”!</translation>
+ </message>
+</context>
<context>
<name>BanTableModel</name>
<message>
<source>Banned Until</source>
- <translation type="unfinished">ห้ามจนถึง</translation>
+ <translation type="unfinished">ห้าม จนถึง</translation>
</message>
</context>
<context>
<name>BitcoinApplication</name>
<message>
- <source>Internal error</source>
- <translation type="unfinished">ข้อผิดพลาดภายใน</translation>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">ไฟล์ตั้งค่า%1 อาจเสียหายหรือไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
</message>
</context>
<context>
@@ -196,41 +259,84 @@
<translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาดร้ายà¹à¸£à¸‡à¸‚ึ้น, โปรดตรวจสอบว่าไฟล์ตั้งค่านั้นสามารถเขียนทับได้หรือลองใช้งานด้วยคำสั่ง -nosettings</translation>
</message>
<message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation type="unfinished">ข้อผิดพลาด: ข้อมูล ไดเร็à¸à¸—อรี ที่เจาะจง "%1" นั้น ไม่ มี</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation type="unfinished">ข้อผิดพลาด: ไม่สามารถ parse configuration ไฟล์: %1.</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">ข้อผิดพลาด: %1</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 ยังไม่ออà¸à¸­à¸¢à¹ˆà¸²à¸‡à¸›à¸¥à¸­à¸”ภัย...</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation type="unfinished">ไม่ทราบ</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation type="unfinished">จำนวน</translation>
</message>
+ <message>
+ <source>Internal</source>
+ <translation type="unfinished">ภายใน</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
+ <translation type="unfinished">ขาเข้า</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <extracomment>An outbound connection to a peer. An outbound connection is a connection initiated by us.</extracomment>
+ <translation type="unfinished">ขาออà¸</translation>
+ </message>
+ <message>
+ <source>Manual</source>
+ <extracomment>Peer connection type established manually through one of several methods.</extracomment>
+ <translation type="unfinished">คู่มือ</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation type="unfinished">ไม่มี</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation type="unfinished">%1 มิลลิวินาที</translation>
+ </message>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform>%n วินาที</numerusform>
+ <numerusform>%nวินาที</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform>%n นาที</numerusform>
+ <numerusform>%nนาที</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform>%n ชั่วโมง</numerusform>
+ <numerusform>%nชั่วโมง</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform>%n วัน</numerusform>
+ <numerusform>%nวัน</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform>%n สัปดาห์</numerusform>
+ <numerusform>%nสัปดาห์</numerusform>
</translation>
</message>
<message>
@@ -240,10 +346,26 @@
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform>%n ปี</numerusform>
+ <numerusform>%nปี</numerusform>
</translation>
</message>
- </context>
+ <message>
+ <source>%1 B</source>
+ <translation type="unfinished">%1 ไบต์</translation>
+ </message>
+ <message>
+ <source>%1 kB</source>
+ <translation type="unfinished">%1 à¸à¸´à¹‚ลไบต์</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation type="unfinished">%1 เมà¸à¸°à¹„บต์</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation type="unfinished">%1 จิà¸à¸°à¹„บต์</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
<message>
@@ -255,18 +377,334 @@
<translation type="unfinished">ไม่สามารถเขียนข้อมูลลงบนไฟล์ตั้งค่าได้</translation>
</message>
<message>
+ <source>The %s developers</source>
+ <translation type="unfinished">%s นัà¸à¸žà¸±à¸’นา</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
+ <translation type="unfinished">ข้อผิดพลาด: ดัมพ์ไฟล์เวอร์ชัน ไม่รองรับเวอร์ชัน บิตคอยน์-วอลเล็ต รุ่นนี้รองรับไฟล์ดัมพ์เวอร์ชัน 1 เท่านั้น รับดัมพ์ไฟล์พร้อมเวอร์ชัน %s</translation>
+ </message>
+ <message>
+ <source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
+ <translation type="unfinished">ข้อผิดพลาด: เลà¸à¸²à¸‹à¸µ วอลเล็ต เพียง สนับสนุน "legacy", "p2sh-segwit", à¹à¸¥à¸° "bech32" ชนิด à¹à¸­à¸”เดรส</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation type="unfinished">จำนวนเงินที่ทำธุรà¸à¸£à¸£à¸¡à¸™à¹‰à¸­à¸¢à¹€à¸à¸´à¸™à¹„ปที่จะส่งหลังจาà¸à¸«à¸±à¸à¸„่าธรรมเนียมà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation type="unfinished">%s ตั้งไว้สูงมาà¸</translation>
+ </message>
+ <message>
<source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
<translation type="unfinished">ไม่สามารถตั้ง -forcednsseed เป็น true ได้เมื่อà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า -dnsseed เป็น false</translation>
</message>
<message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation type="unfinished">ไม่สามารถตั้งค่า -peerblockfilters โดยที่ไม่มี -blockfilterindex</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%sขอฟังความเห็นเรื่องพอร์ต%u พอร์ตนี้ถือว่า "ไม่ดี" ดังนั้นจึงไม่น่าเป็นไปได้ที่ Bitcoin Core จะเชื่อมต่อà¸à¸±à¸šà¸žà¸­à¸£à¹Œà¸•à¸™à¸µà¹‰ ดู doc/p2p-bad-ports.md สำหรับรายละเอียดà¹à¸¥à¸°à¸£à¸²à¸¢à¸à¸²à¸£à¸—ั้งหมด</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาดในà¸à¸²à¸£à¹‚หลด %s: à¸à¸³à¸¥à¸±à¸‡à¹‚หลดวอลเล็ตผู้ลงนามภายนอà¸à¹‚ดยไม่มีà¸à¸²à¸£à¸£à¸§à¸šà¸£à¸§à¸¡à¸à¸²à¸£à¸ªà¸™à¸±à¸šà¸ªà¸™à¸¸à¸™à¸œà¸¹à¹‰à¸¥à¸‡à¸™à¸²à¸¡à¸ à¸²à¸¢à¸™à¸­à¸</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">ไม่สามารถเปลี่ยนชื่อไฟล์ peers.dat ที่ไม่ถูà¸à¸•à¹‰à¸­à¸‡ โปรดย้ายหรือลบà¹à¸¥à¹‰à¸§à¸¥à¸­à¸‡à¸­à¸µà¸à¸„รั้ง</translation>
+ </message>
+ <message>
+ <source>Could not find asmap file %s</source>
+ <translation type="unfinished">ไม่ ตรวจพบ ไฟล์ asmap %s</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation type="unfinished">ไม่ สามารถ à¹à¸¢à¸ วิเคราะห์ ไฟล์ asmap %s</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation type="unfinished">พื้นที่ว่าง ดิสà¸à¹Œ เหลือ น้อย เà¸à¸´à¸™à¹„ป!</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation type="unfinished">คุณต้องà¸à¸²à¸£à¸²à¸£à¹‰à¸²à¸‡à¸à¸²à¸™à¸‚้อมูลบล็อà¸à¹ƒà¸«à¸¡à¹ˆà¸•à¸­à¸™à¸™à¸µà¹‰à¸«à¸£à¸·à¸­à¹„ม่?</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation type="unfinished">à¸à¸²à¸£à¹‚หลด เสร็จสิ้น</translation>
+ </message>
+ <message>
+ <source>Dump file %s does not exist.</source>
+ <translation type="unfinished"> ไม่มีไฟล์ดัมพ์ %s </translation>
+ </message>
+ <message>
+ <source>Error creating %s</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาด ในà¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡%s</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาดในà¸à¸²à¸£à¹€à¸£à¸´à¹ˆà¸¡à¸•à¹‰à¸™à¸à¸²à¸™à¸‚้อมูลบล็อà¸</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation type="unfinished">à¸à¸²à¸£à¹‚หลด เà¸à¸´à¸”ข้อผิดพลาด %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation type="unfinished">à¸à¸²à¸£à¹‚หลดเà¸à¸´à¸”ข้อผิดพลาด %s: Private keys สามารถปิดà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¸£à¸°à¸«à¸§à¹ˆà¸²à¸‡à¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¸‚ึ้นเท่านั้น</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาดในà¸à¸²à¸£à¹‚หลด %s: วอลเล็ตเà¸à¸´à¸”ความเสียหาย</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาดในà¸à¸²à¸£à¹‚หลด %s: วอลเล็ตต้องà¸à¸²à¸£à¹€à¸§à¸­à¸£à¹Œà¸Šà¸±à¸™à¹ƒà¸«à¸¡à¹ˆà¸à¸§à¹ˆà¸² %s</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาด ในà¸à¸²à¸£à¹‚หลด à¸à¸²à¸™à¸‚้อมูล บล็อà¸</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาด ในà¸à¸²à¸£à¹€à¸›à¸´à¸” à¸à¸²à¸™à¸‚้อมูล บล็อà¸</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาด ในà¸à¸²à¸£à¸­à¹ˆà¸²à¸™ จาภà¸à¸²à¸™à¸‚้อมูล, à¸à¸³à¸¥à¸±à¸‡à¸›à¸´à¸”</translation>
+ </message>
+ <message>
+ <source>Error reading next record from wallet database</source>
+ <translation type="unfinished">เà¸à¸´à¸”ข้อผิดพลาด ในà¸à¸²à¸£à¸­à¹ˆà¸²à¸™ บันทึภถัดไป จาภà¸à¸²à¸™à¸‚้อมูล วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Error: Couldn't create cursor into database</source>
+ <translation type="unfinished">ข้อผิดพลาด: ไม่สามารถ สร้าง เคอร์เซอร์ ใน à¸à¸²à¸™à¸‚้อมูล</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low for %s</source>
+ <translation type="unfinished">ข้อผิดพลาด: พื้นที่ ดิสà¸à¹Œ เหลือน้อย สำหรับ %s</translation>
+ </message>
+ <message>
+ <source>Error: Missing checksum</source>
+ <translation type="unfinished">ข้อผิดพลาด: ไม่มี เช็คซัม</translation>
+ </message>
+ <message>
+ <source>Error: No %s addresses available.</source>
+ <translation type="unfinished">ข้อผิดพลาด: ไม่มี %s à¹à¸­à¸”เดรสพร้อมใช้งาน</translation>
+ </message>
+ <message>
+ <source>Error: Unable to write record to new wallet</source>
+ <translation type="unfinished">ข้อผิดพลาด: ไม่สามารถเขียนบันทึà¸à¹„ปยังวอลเล็ตใหม่</translation>
+ </message>
+ <message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation type="unfinished">ไม่สามารถสà¹à¸à¸™à¸§à¸­à¸¥à¹€à¸¥à¹‡à¸•à¸­à¸µà¸à¸„รั้งในระหว่างà¸à¸²à¸£à¹€à¸£à¸´à¹ˆà¸¡à¸•à¹‰à¸™</translation>
+ </message>
+ <message>
+ <source>Failed to verify database</source>
+ <translation type="unfinished">ไม่สามารถตรวจสอบà¸à¸²à¸™à¸‚้อมูล</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation type="unfinished">อัตราค่าธรรมเนียม (%s) ต่ำà¸à¸§à¹ˆà¸²à¸­à¸±à¸•à¸£à¸²à¸„่าธรรมเนียมขั้นต่ำที่ตั้งไว้ (%s)</translation>
+ </message>
+ <message>
+ <source>Ignoring duplicate -wallet %s.</source>
+ <translation type="unfinished">ละเว้นà¸à¸²à¸£à¸—ำซ้ำ -วอลเล็ต %s.</translation>
+ </message>
+ <message>
+ <source>Importing…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸™à¸³à¹€à¸‚้า…</translation>
+ </message>
+ <message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">ไม่พบข้อมูลที่ป้อนหรือใช้ไปà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation type="unfinished">เงินทุน ไม่เพียงพอ</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¹‚หลด P2P addresses…</translation>
+ </message>
+ <message>
+ <source>Loading banlist…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¹‚หลด banlist…</translation>
+ </message>
+ <message>
+ <source>Loading block index…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¹‚หลด block index…</translation>
+ </message>
+ <message>
+ <source>Loading wallet…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¹‚หลด วอลเล็ต...</translation>
+ </message>
+ <message>
<source>Missing amount</source>
- <translation type="unfinished">จำนวนที่หายไป</translation>
+ <translation type="unfinished">จำนวน ที่หายไป</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">ไม่มีข้อมูลà¸à¸²à¸£à¹à¸à¹‰à¹„ขสำหรับà¸à¸²à¸£à¸›à¸£à¸°à¸¡à¸²à¸“ค่าขนาดธุรà¸à¸£à¸£à¸¡</translation>
</message>
<message>
<source>No addresses available</source>
- <translation type="unfinished">ไม่มีที่อยู่ที่ใช้งานได้</translation>
+ <translation type="unfinished">ไม่มี à¹à¸­à¸”เดรส ที่ใช้งานได้</translation>
</message>
- </context>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation type="unfinished">มีตัวอธิบายไฟล์ไม่เพียงพอ</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation type="unfinished">ไม่สามารถà¸à¸³à¸«à¸™à¸”ค่าพรุนด้วยค่าลบ</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation type="unfinished">โหมดพรุนเข้าà¸à¸±à¸™à¹„ม่ได้à¸à¸±à¸š -txindex</translation>
+ </message>
+ <message>
+ <source>Rescanning…</source>
+ <translation type="unfinished">ทำà¸à¸²à¸£à¸ªà¹à¸à¸™à¸‹à¹‰à¸³â€¦</translation>
+ </message>
+ <message>
+ <source>Section [%s] is not recognized.</source>
+ <translation type="unfinished">ส่วน [%s] ไม่เป็นที่รู้จัà¸</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation type="unfinished">Specified -walletdir "%s" ไม่มีอยู่</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation type="unfinished">Specified -walletdir "%s" เป็นพาธสัมพัทธ์</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation type="unfinished">Specified -walletdir "%s" ไม่ใช่ไดเร็à¸à¸—อรี</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation type="unfinished">ไม่มีไดเร็à¸à¸—อรีบล็อà¸à¸—ี่ระบุ "%s" </translation>
+ </message>
+ <message>
+ <source>Starting network threads…</source>
+ <translation type="unfinished">à¸à¸²à¸£à¹€à¸£à¸´à¹ˆà¸¡à¹€à¸˜à¸£à¸”เครือข่าย…</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation type="unfinished">ซอร์สโค๊ดสามารถใช้ได้จาภ%s.</translation>
+ </message>
+ <message>
+ <source>The specified config file %s does not exist</source>
+ <translation type="unfinished">ไฟล์à¸à¸³à¸«à¸™à¸”ค่าที่ระบุ %s ไม่มีอยู่</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation type="unfinished">จำนวนธุรà¸à¸£à¸£à¸¡à¸™à¹‰à¸­à¸¢à¹€à¸à¸´à¸™à¹„ปที่จะชำระค่าธรรมเนียม</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation type="unfinished">วอลเล็ตจะหลีà¸à¹€à¸¥à¸µà¹ˆà¸¢à¸‡à¸à¸²à¸£à¸ˆà¹ˆà¸²à¸¢à¸™à¹‰à¸­à¸¢à¸à¸§à¹ˆà¸²à¸„่าธรรมเนียมรีเลย์ขั้นต่ำ</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation type="unfinished">นี่คือซอฟต์à¹à¸§à¸£à¹Œà¸—ดลอง</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation type="unfinished">นี่คือค่าธรรมเนียมà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡à¸‚ั้นต่ำที่คุณจ่ายในทุà¸à¸˜à¸¸à¸£à¸à¸£à¸£à¸¡</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation type="unfinished">นี่คือค่าธรรมเนียมà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡à¸—ี่คุณจะจ่ายหาà¸à¸„ุณส่งธุรà¸à¸£à¸£à¸¡</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation type="unfinished">จำนวนธุรà¸à¸£à¸£à¸¡à¸™à¹‰à¸­à¸¢à¹€à¸à¸´à¸™à¹„ป</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation type="unfinished">จำนวนเงินที่ทำธุรà¸à¸£à¸£à¸¡à¸•à¹‰à¸­à¸‡à¹„ม่เป็นค่าติดลบ</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation type="unfinished">ธุรà¸à¸£à¸£à¸¡à¸¡à¸µ เชนเมมพูล ยาวเà¸à¸´à¸™à¹„ป</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation type="unfinished">ธุรà¸à¸£à¸£à¸¡à¸•à¹‰à¸­à¸‡à¸¡à¸µà¸œà¸¹à¹‰à¸£à¸±à¸šà¸­à¸¢à¹ˆà¸²à¸‡à¸™à¹‰à¸­à¸¢à¸«à¸™à¸¶à¹ˆà¸‡à¸£à¸²à¸¢</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡à¸•à¹‰à¸­à¸‡à¸à¸²à¸£à¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹à¸›à¸¥à¸‡à¸—ี่อยู่ à¹à¸•à¹ˆà¹€à¸£à¸²à¹„ม่สามารถสร้างมันขึ้นมาได้</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation type="unfinished">ธุรà¸à¸£à¸£à¸¡à¹ƒà¸«à¸à¹ˆà¹€à¸à¸´à¸™à¹„ป</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation type="unfinished">ไม่สามารถผูภ%s บนคอมพิวเตอร์นี้ %s อาจเนื่องมาจาà¸à¹€à¸„ยใช้à¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>Unable to create the PID file '%s': %s</source>
+ <translation type="unfinished">ไม่สามารถสร้างไฟล์ PID '%s': %s</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation type="unfinished">ไม่สามารถ สร้าง คีย์ เริ่มต้น</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation type="unfinished">ไม่สามารถ สร้าง คีย์</translation>
+ </message>
+ <message>
+ <source>Unable to open %s for writing</source>
+ <translation type="unfinished">ไม่สามารถเปิด %s สำหรับà¸à¸²à¸£à¹€à¸‚ียนข้อมูล</translation>
+ </message>
+ <message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation type="unfinished">ไม่รู้จัภ-ค่า blockfilterindex value %s</translation>
+ </message>
+ <message>
+ <source>Unknown address type '%s'</source>
+ <translation type="unfinished">ไม่รู้จัภประเภท à¹à¸­à¸”เดรส '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation type="unfinished">ไม่รู้จัภประเภท à¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹à¸›à¸¥à¸‡ '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation type="unfinished">ไม่รู้จัภเครือข่าย ที่ระบุ ใน -onlynet: '%s'</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">หมวดหมู่à¸à¸²à¸£à¸šà¸±à¸™à¸—ึà¸à¸—ี่ไม่รองรับ %s=%s</translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation type="unfinished">ความคิดเห็นของ User Agent (%s) มีอัà¸à¸‚ระที่ไม่ปลอดภัย</translation>
+ </message>
+ <message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸š บล็อà¸â€¦</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸š วอลเล็ต…</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation type="unfinished">ต้องเขียน Wallet ใหม่: restart %s เพื่อให้เสร็จสิ้น</translation>
+ </message>
+</context>
<context>
<name>BitcoinGUI</name>
<message>
@@ -275,23 +713,19 @@
</message>
<message>
<source>Show general overview of wallet</source>
- <translation type="unfinished">à¹à¸ªà¸”งภาพรวมทั่วไปของà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">à¹à¸ªà¸”ง ภาพรวม ทั่วไป ของ วอลเล็ต</translation>
</message>
<message>
<source>&amp;Transactions</source>
- <translation type="unfinished">&amp;ธุรà¸à¸£à¸£à¸¡</translation>
+ <translation type="unfinished">&amp;à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
</message>
<message>
<source>Browse transaction history</source>
- <translation type="unfinished">เรียà¸à¸”ูประวัติà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation type="unfinished">&amp;ออà¸</translation>
+ <translation type="unfinished">เรียà¸à¸”ู ประวัติ à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
</message>
<message>
<source>Quit application</source>
- <translation type="unfinished">ออà¸à¸ˆà¸²à¸à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชัน</translation>
+ <translation type="unfinished">ออà¸à¸ˆà¸²à¸ à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชัน</translation>
</message>
<message>
<source>&amp;About %1</source>
@@ -299,7 +733,7 @@
</message>
<message>
<source>Show information about %1</source>
- <translation type="unfinished">à¹à¸ªà¸”งข้อมูลเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š %1</translation>
+ <translation type="unfinished">à¹à¸ªà¸”ง ข้อมูล เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š %1</translation>
</message>
<message>
<source>About &amp;Qt</source>
@@ -307,15 +741,15 @@
</message>
<message>
<source>Show information about Qt</source>
- <translation type="unfinished">à¹à¸ªà¸”งข้อมูลเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š Qt</translation>
+ <translation type="unfinished">à¹à¸ªà¸”ง ข้อมูล เà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸š Qt</translation>
</message>
<message>
<source>Modify configuration options for %1</source>
- <translation type="unfinished">ปรับเปลี่ยนตัวเลือà¸à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าสำหรับ %1</translation>
+ <translation type="unfinished">ปรับเปลี่ยน ตัวเลือภà¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่า สำหรับ %1</translation>
</message>
<message>
<source>Create a new wallet</source>
- <translation type="unfinished">สร้างà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">สร้าง วอลเล็ต ใหม่</translation>
</message>
<message>
<source>&amp;Minimize</source>
@@ -323,19 +757,28 @@
</message>
<message>
<source>Wallet:</source>
- <translation type="unfinished">à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์:</translation>
+ <translation type="unfinished">วอลเล็ต:</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">à¸à¸´à¸ˆà¸à¸£à¸£à¸¡ เครือข่าย ถูà¸à¸›à¸´à¸”ใช้งาน</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation type="unfinished">พร็อà¸à¸‹à¸µà¹ˆ ถูภ&lt;b&gt;เปิดใช้งาน&lt;/b&gt;: %1</translation>
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation type="unfinished">ส่งเหรียà¸à¹„ปยังที่อยู่ Bitcoin</translation>
+ <translation type="unfinished">ส่ง เหรียภไปยัง Bitcoin à¹à¸­à¸”เดรส</translation>
</message>
<message>
<source>Backup wallet to another location</source>
- <translation type="unfinished">สำรองข้อมูลà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ไปยังตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่ตั้งอื่น</translation>
+ <translation type="unfinished">à¹à¸šà¹‡à¸„อัพวอลเล็ตไปยังตำà¹à¸«à¸™à¹ˆà¸‡à¸—ี่ตั้งอื่น</translation>
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
- <translation type="unfinished">เปลี่ยนรหัสผ่านที่ใช้สำหรับà¸à¸²à¸£à¹€à¸‚้ารหัสà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¹€à¸‡à¸´à¸™</translation>
+ <translation type="unfinished">เปลี่ยน พาสเฟส ที่ใช้ สำหรับ à¸à¸²à¸£à¹€à¸‚้ารหัส วอลเล็ต</translation>
</message>
<message>
<source>&amp;Send</source>
@@ -347,39 +790,59 @@
</message>
<message>
<source>&amp;Options…</source>
- <translation type="unfinished">&amp;ตั้งค่า…</translation>
+ <translation type="unfinished">&amp;ตัวเลือà¸â€¦</translation>
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
- <translation type="unfinished">&amp;เข้ารหัสà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์...</translation>
+ <translation type="unfinished">&amp;เข้ารหัส วอลเล็ต...</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">เข้ารหัสà¸à¸¸à¸à¹à¸ˆà¸ªà¹ˆà¸§à¸™à¸•à¸±à¸§à¸—ี่เป็นของà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ของคุณ</translation>
</message>
<message>
<source>&amp;Backup Wallet…</source>
- <translation type="unfinished">&amp;สำรองข้อมูลà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์...</translation>
+ <translation type="unfinished">&amp;à¹à¸šà¹‡à¸„อัพวอลเล็ต…</translation>
</message>
<message>
<source>&amp;Change Passphrase…</source>
- <translation type="unfinished">&amp;เปลี่ยนวลีรหัสผ่าน...</translation>
+ <translation type="unfinished">&amp;เปลี่ยน พาสเฟส...</translation>
</message>
<message>
<source>Sign &amp;message…</source>
- <translation type="unfinished">&amp;เซ็นข้อความ...</translation>
+ <translation type="unfinished">เซ็น &amp;ข้อความ...</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished">เซ็นชื่อด้วยข้อความ ที่เà¸à¹‡à¸š Bitcoin เพื่อà¹à¸ªà¸”งว่าท่านเป็นเจ้าของ bitcoin นี้จริง</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;ยืนยัน ข้อความ…</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">ตรวจสอบ ข้อความ เพื่อให้à¹à¸™à¹ˆà¹ƒà¸ˆà¸§à¹ˆà¸² à¸à¸²à¸£à¹€à¸‹à¹‡à¸™à¸•à¹Œà¸Šà¸·à¹ˆà¸­ ด้วยที่เà¸à¹‡à¸š Bitcoin à¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">&amp;โหลด PSBT จาภไฟล์...</translation>
</message>
<message>
<source>Open &amp;URI…</source>
- <translation type="unfinished">&amp;เปิด URI...</translation>
+ <translation type="unfinished">เปิด &amp;URI…</translation>
</message>
<message>
<source>Close Wallet…</source>
- <translation type="unfinished">ปิดà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">ปิด วอลเล็ต…</translation>
</message>
<message>
<source>Create Wallet…</source>
- <translation type="unfinished">สร้างà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ใหม่</translation>
+ <translation type="unfinished">สร้าง วอลเล็ต…</translation>
</message>
<message>
<source>Close All Wallets…</source>
- <translation type="unfinished">ปิดà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ทั้งหมด...</translation>
+ <translation type="unfinished">ปิด วอลเล็ต ทั้งหมด...</translation>
</message>
<message>
<source>&amp;File</source>
@@ -395,23 +858,43 @@
</message>
<message>
<source>Tabs toolbar</source>
- <translation type="unfinished">à¹à¸–บเครื่องมือà¹à¸—็บ</translation>
+ <translation type="unfinished">à¹à¸–บ เครื่องมือ</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸‹à¸´à¸‡à¸„์ส่วนหัว (%1%)…</translation>
</message>
<message>
<source>Synchronizing with network…</source>
- <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸‹à¸´à¸‡à¸„์ข้อมูลà¸à¸±à¸šà¸—างเครือข่าย ...</translation>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸‹à¸´à¸‡à¸„์ข้อมูล à¸à¸±à¸šà¸—าง เครือข่าย ...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¸”ัชนีบล็อà¸à¸šà¸™à¸”ิสà¸à¹Œâ€¦</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸›à¸£à¸°à¸¡à¸§à¸¥à¸œà¸¥à¸šà¸¥à¹‡à¸­à¸à¸šà¸™à¸”ิสà¸à¹Œâ€¦</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¸”ัชนีบล็อà¸à¹ƒà¸«à¸¡à¹ˆà¸šà¸™à¸”ิสà¸à¹Œâ€¦</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­ ไปยัง peers…</translation>
</message>
<message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation type="unfinished">เรียà¸à¹€à¸à¹‡à¸š à¸à¸²à¸£à¸Šà¸³à¸£à¸°à¹€à¸‡à¸´à¸™ (สร้าง QR codes à¹à¸¥à¸° bitcoin: URIs)</translation>
+ <translation type="unfinished">ขอà¸à¸²à¸£à¸Šà¸³à¸£à¸°à¹€à¸‡à¸´à¸™ (สร้างรหัส QR à¹à¸¥à¸° bitcoin: URIs)</translation>
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
- <translation type="unfinished">à¹à¸ªà¸”งรายà¸à¸²à¸£ ที่เà¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¸—ี่จะส่ง bitcoin ออภà¹à¸¥à¸°à¸›à¹‰à¸²à¸¢à¸Šà¸·à¹ˆà¸­ ที่ใช้ไปà¹à¸¥à¹‰à¸§</translation>
+ <translation type="unfinished">à¹à¸ªà¸”งรายà¸à¸²à¸£à¸—ี่ใช้ในà¸à¸²à¸£à¸ªà¹ˆà¸‡à¹à¸­à¸”เดรสà¹à¸¥à¸°à¹€à¸¥à¹€à¸šà¸¥à¸—ี่ใช้à¹à¸¥à¹‰à¸§</translation>
</message>
<message>
<source>Show the list of used receiving addresses and labels</source>
- <translation type="unfinished">à¹à¸ªà¸”งรายà¸à¸²à¸£ ที่เà¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¸—ี่จะรับ bitcoin เข้า à¹à¸¥à¸°à¸›à¹‰à¸²à¸¢à¸Šà¸·à¹ˆà¸­ ที่ใช้ไปà¹à¸¥à¹‰à¸§</translation>
+ <translation type="unfinished">à¹à¸ªà¸”งรายà¸à¸²à¸£à¸—ี่ได้ใช้ในà¸à¸²à¸£à¸£à¸±à¸šà¹à¸­à¸”เดรสà¹à¸¥à¸°à¹€à¸¥à¹€à¸šà¸¥</translation>
</message>
<message>
<source>&amp;Command-line options</source>
@@ -420,20 +903,24 @@
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>ประมวลผล %n บล็อà¸à¸‚องประวัติà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</numerusform>
</translation>
</message>
<message>
<source>%1 behind</source>
- <translation type="unfinished">%1 ตามหลัง</translation>
+ <translation type="unfinished">%1 เบื้องหลัง</translation>
+ </message>
+ <message>
+ <source>Catching up…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸•à¸´à¸”ตามถึงรายà¸à¸²à¸£à¸¥à¹ˆà¸²à¸ªà¸¸à¸”…</translation>
</message>
<message>
<source>Last received block was generated %1 ago.</source>
- <translation type="unfinished">บล็อà¸à¸ªà¸¸à¸”ท้ายที่ได้รับ สร้างขึ้นเมื่อ %1 มาà¹à¸¥à¹‰à¸§</translation>
+ <translation type="unfinished">บล็อà¸à¸—ี่ได้รับล่าสุดถูà¸à¸ªà¸£à¹‰à¸²à¸‡à¸‚ึ้นเมื่อ %1 ที่à¹à¸¥à¹‰à¸§</translation>
</message>
<message>
<source>Transactions after this will not yet be visible.</source>
- <translation type="unfinished">ธุรà¸à¸£à¸£à¸¡à¸«à¸¥à¸±à¸‡à¸ˆà¸²à¸à¸™à¸µà¹‰à¸ˆà¸°à¸¢à¸±à¸‡à¹„ม่สามารถมองเห็น</translation>
+ <translation type="unfinished">ธุรà¸à¸£à¸£à¸¡à¸«à¸¥à¸±à¸‡à¸ˆà¸²à¸à¸™à¸µà¹‰à¸ˆà¸°à¸¢à¸±à¸‡à¹„ม่ปราà¸à¸à¹ƒà¸«à¹‰à¹€à¸«à¹‡à¸™</translation>
</message>
<message>
<source>Error</source>
@@ -449,7 +936,85 @@
</message>
<message>
<source>Up to date</source>
- <translation type="unfinished">ทันสมัย</translation>
+ <translation type="unfinished">ปัจจุบัน</translation>
+ </message>
+ <message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">โหลด PSBT จาà¸à¸„ลิปบอร์ด...</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">หน้าต่างโหนด</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished">&amp;ที่อยู่à¸à¸²à¸£à¸ªà¹ˆà¸‡</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished">&amp;ที่อยู่à¸à¸²à¸£à¸£à¸±à¸š</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation type="unfinished">เปิดà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ </message>
+ <message>
+ <source>Open a wallet</source>
+ <translation type="unfinished">เปิดà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">ปิดà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ </message>
+ <message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">à¸à¸¹à¹‰à¸„ืนวอลเล็ต…</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">à¸à¸¹à¹‰à¸„ืนวอลเล็ตจาà¸à¹„ฟล์สำรองข้อมูล</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">ปิด วอลเล็ต ทั้งหมด</translation>
+ </message>
+ <message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">&amp;ค่ามาสà¸à¹Œ</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">วอลเล็ต เริ่มต้น</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation type="unfinished">ไม่มี วอลเล็ต ที่พร้อมใช้งาน</translation>
+ </message>
+ <message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">ข้อมูล วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">โหลดสำรองข้อมูลวอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">à¸à¸¹à¹‰à¸„ืนวอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">ชื่อ วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;วินโดว์</translation>
</message>
<message>
<source>Zoom</source>
@@ -457,7 +1022,7 @@
</message>
<message>
<source>Main Window</source>
- <translation type="unfinished">หน้าต่างหลัà¸</translation>
+ <translation type="unfinished">วินโดว์ หลัà¸</translation>
</message>
<message>
<source>%1 client</source>
@@ -469,16 +1034,36 @@
</message>
<message>
<source>S&amp;how</source>
- <translation type="unfinished">à¹à¸ªà¸”ง</translation>
+ <translation type="unfinished">&amp;à¹à¸ªà¸”ง</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform>%n à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸—ี่ใช้งานได้ เพื่อเชื่อมà¸à¸±à¸šà¹€à¸„รือข่าย Bitcoin</numerusform>
+ <numerusform>%n เครือข่ายที่สามารถใช้เชื่อมต่อไปยังเครือข่ายบิตคอยน์ได้</numerusform>
</translation>
</message>
<message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">คลิà¸à¹€à¸žà¸·à¹ˆà¸­à¸”ูà¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¹€à¸žà¸´à¹ˆà¸¡à¹€à¸•à¸´à¸¡</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">à¹à¸ªà¸”ง Peers à¹à¸—็ป</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">ปิดใช้งาน à¸à¸´à¸ˆà¸à¸£à¸£à¸¡ เครือข่าย</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">เปิดใช้งาน à¸à¸´à¸ˆà¸à¸£à¸£à¸¡ เครือข่าย</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">ข้อผิดพลาด: %1</translation>
</message>
@@ -501,61 +1086,80 @@
<message>
<source>Wallet: %1
</source>
- <translation type="unfinished">à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์: %1
+ <translation type="unfinished">วอลเล็ต: %1
</translation>
</message>
<message>
<source>Type: %1
</source>
- <translation type="unfinished">ชนิด: %1
+ <translation type="unfinished">รูปà¹à¸šà¸š: %1
</translation>
</message>
<message>
<source>Label: %1
</source>
- <translation type="unfinished">ป้ายชื่อ: %1
+ <translation type="unfinished">เลเบล: %1
</translation>
</message>
<message>
<source>Address: %1
</source>
- <translation type="unfinished">ที่อยู่: %1
+ <translation type="unfinished">à¹à¸­à¸”เดรส: %1
</translation>
</message>
<message>
<source>Sent transaction</source>
- <translation type="unfinished">รายà¸à¸²à¸£à¸—ี่ส่ง</translation>
+ <translation type="unfinished">รายà¸à¸²à¸£ ที่ส่ง</translation>
</message>
<message>
<source>Incoming transaction</source>
- <translation type="unfinished">à¸à¸²à¸£à¸—ำรายà¸à¸²à¸£à¸‚าเข้า</translation>
+ <translation type="unfinished">à¸à¸²à¸£à¸—ำรายà¸à¸²à¸£ ขาเข้า</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation type="unfinished">HD key generation ถูภ&lt;b&gt;เปิดใช้งาน&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">HD key generation ถูภ&lt;b&gt;ปิดใช้งาน&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">คีย์ ส่วนตัว &lt;b&gt;ถูà¸à¸›à¸´à¸”ใช้งาน&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation type="unfinished">ระเป๋าเงินถูภ&lt;b&gt;เข้ารหัส&lt;/b&gt; à¹à¸¥à¸°à¹ƒà¸™à¸‚ณะนี้ &lt;b&gt;ปลดล็อคà¹à¸¥à¹‰à¸§&lt;/b&gt;</translation>
+ <translation type="unfinished">วอลเล็ต ถูภ&lt;b&gt;เข้ารหัส&lt;/b&gt; à¹à¸¥à¸° ในขณะนี้ &lt;b&gt;ปลดล็อคà¹à¸¥à¹‰à¸§&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation type="unfinished">à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¹€à¸‡à¸´à¸™à¸–ูภ&lt;b&gt;เข้ารหัส&lt;/b&gt; à¹à¸¥à¸°à¹ƒà¸™à¸›à¸±à¸ˆà¸ˆà¸¸à¸šà¸±à¸™ &lt;b&gt;ล็อค &lt;/b&gt;</translation>
+ <translation type="unfinished">วอลเล็ต ถูภ&lt;b&gt;เข้ารหัส&lt;/b&gt; à¹à¸¥à¸° ในขณะนี้ &lt;b&gt;ล็อคà¹à¸¥à¹‰à¸§ &lt;/b&gt;</translation>
</message>
<message>
<source>Original message:</source>
- <translation type="unfinished">ข้อความดั้งเดิม:</translation>
+ <translation type="unfinished">ข้อความ ดั้งเดิม:</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">หน่วยà¹à¸ªà¸”งจำนวนเงิน คลิà¸à¹€à¸žà¸·à¹ˆà¸­à¹€à¸¥à¸·à¸­à¸à¸«à¸™à¹ˆà¸§à¸¢à¸­à¸·à¹ˆà¸™</translation>
</message>
</context>
<context>
<name>CoinControlDialog</name>
<message>
<source>Coin Selection</source>
- <translation type="unfinished">à¸à¸²à¸£à¹€à¸¥à¸·à¸­à¸à¹€à¸«à¸£à¸µà¸¢à¸</translation>
+ <translation type="unfinished">à¸à¸²à¸£à¹€à¸¥à¸·à¸­à¸à¸„อยน์</translation>
</message>
<message>
<source>Quantity:</source>
- <translation type="unfinished">จำนวน:</translation>
+ <translation type="unfinished">ปริมาณ:</translation>
</message>
<message>
<source>Bytes:</source>
- <translation type="unfinished">ไบต์:</translation>
+ <translation type="unfinished">ไบทส์:</translation>
</message>
<message>
<source>Amount:</source>
@@ -567,27 +1171,27 @@
</message>
<message>
<source>Dust:</source>
- <translation type="unfinished">เศษ:</translation>
+ <translation type="unfinished">ดัสท์:</translation>
</message>
<message>
<source>After Fee:</source>
- <translation type="unfinished">ส่วนที่เหลือจาà¸à¸„่าธรรมเนียม:</translation>
+ <translation type="unfinished">หลังค่าธรรมเนียม:</translation>
</message>
<message>
<source>Change:</source>
- <translation type="unfinished">เงินทอน:</translation>
+ <translation type="unfinished">เปลี่ยน:</translation>
</message>
<message>
<source>(un)select all</source>
- <translation type="unfinished">(ไม่)เลือà¸à¸—ั้งหมด</translation>
+ <translation type="unfinished">(un)เลือà¸à¸—ั้งหมด</translation>
</message>
<message>
<source>Tree mode</source>
- <translation type="unfinished">โหมดà¹à¸šà¸šà¸•à¹‰à¸™à¹„ม้</translation>
+ <translation type="unfinished">โหมด à¹à¸šà¸šTree</translation>
</message>
<message>
<source>List mode</source>
- <translation type="unfinished">โหมดà¹à¸šà¸šà¸£à¸²à¸¢à¸à¸²à¸£</translation>
+ <translation type="unfinished">โหมด à¹à¸šà¸šà¸£à¸²à¸¢à¸à¸²à¸£</translation>
</message>
<message>
<source>Amount</source>
@@ -595,11 +1199,11 @@
</message>
<message>
<source>Received with label</source>
- <translation type="unfinished">รับด้วยป้ายชื่อ</translation>
+ <translation type="unfinished">รับ ด้วย เลเบล</translation>
</message>
<message>
<source>Received with address</source>
- <translation type="unfinished">รับด้วยที่อยู่</translation>
+ <translation type="unfinished">รับ ด้วย à¹à¸­à¸”เดรส</translation>
</message>
<message>
<source>Date</source>
@@ -607,7 +1211,7 @@
</message>
<message>
<source>Confirmations</source>
- <translation type="unfinished">à¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™</translation>
+ <translation type="unfinished">ทำà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™</translation>
</message>
<message>
<source>Confirmed</source>
@@ -615,15 +1219,75 @@
</message>
<message>
<source>Copy amount</source>
- <translation type="unfinished">คัดลอà¸à¸ˆà¸³à¸™à¸§à¸™à¹€à¸‡à¸´à¸™</translation>
+ <translation type="unfinished">คัดลอภจำนวน</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;คัดลอภà¹à¸­à¸”เดรส</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">คัดลอภ&amp;เลเบล</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">คัดลอภ&amp;จำนวน</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">คัดล็อภ&amp;ID ธุรà¸à¸£à¸£à¸¡ à¹à¸¥à¸° ส่งออภเป็นดัชนี</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">L&amp;ock ที่ไม่ได้ใข้</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">&amp;ปลดล็อค ที่ไม่ไดใช้</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">คัดลอภปริมาณ</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">คัดลอภค่าธรรมเนียม</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">คัดลอภหลัง ค่าธรรมเนียม</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">คัดลอภbytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">คัดลอภdust</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">คัดลอภchange</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation type="unfinished">(%1 ล็อคà¹à¸¥à¹‰à¸§)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation type="unfinished">ใช่</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation type="unfinished">ไม่</translation>
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ไม่มีป้ายชื่อ)</translation>
+ <translation type="unfinished">(ไม่มีเลเบล)</translation>
</message>
<message>
<source>change from %1 (%2)</source>
- <translation type="unfinished">เปลี่ยนจาภ%1 (%2)</translation>
+ <translation type="unfinished">เปลี่ยน จาภ%1 (%2)</translation>
</message>
<message>
<source>(change)</source>
@@ -635,7 +1299,24 @@
<message>
<source>Create Wallet</source>
<extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
- <translation type="unfinished">สร้างà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">สร้าง วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸ªà¸£à¹‰à¸²à¸‡ วอลเล็ต &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡ วอลเล็ต ล้มเหลว</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation type="unfinished">คำเตือน à¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡ วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">ไม่สามารถ จัดรายà¸à¸²à¸£ ผู้เซ็น</translation>
</message>
</context>
<context>
@@ -643,26 +1324,67 @@
<message>
<source>Load Wallets</source>
<extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
- <translation type="unfinished">โหลดà¸à¸£à¸°à¹€à¸›à¹‹à¸²</translation>
+ <translation type="unfinished">โหลด วอลเล็ต</translation>
</message>
<message>
<source>Loading wallets…</source>
<extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
- <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¹‚หลดà¸à¸£à¸°à¹€à¸›à¹‹à¸²...</translation>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¹‚หลด วอลเล็ต...</translation>
</message>
</context>
<context>
<name>OpenWalletActivity</name>
<message>
+ <source>Open wallet failed</source>
+ <translation type="unfinished">เปิด วอลเล็ต ล้มเหลว</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation type="unfinished">คำเตือน à¸à¸²à¸£à¹€à¸›à¸´à¸” วอลเล็ต</translation>
+ </message>
+ <message>
<source>default wallet</source>
- <translation type="unfinished">à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์เริ่มต้น</translation>
+ <translation type="unfinished">วอลเล็ต เริ่มต้น</translation>
</message>
<message>
<source>Open Wallet</source>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">เปิดà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
</message>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¹€à¸›à¸´à¸” วอลเล็ต &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+</context>
+<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">à¸à¸¹à¹‰à¸„ืนวอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">ทำà¸à¸²à¸£à¸à¸¹à¹‰à¸„ืนวอลเล็ต &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">à¸à¸²à¸£à¸à¸¹à¹‰à¸„ืนวอลเล็ตล้มเหลว</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">คำเตือนà¸à¸²à¸£à¸à¸¹à¹‰à¸„ืนวอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">ข้อความà¸à¸²à¸£à¸à¸¹à¹‰à¸„ืนวอลเล็ต</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
@@ -670,116 +1392,162 @@
<translation type="unfinished">ปิดà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
</message>
<message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation type="unfinished">คุณ à¹à¸™à¹ˆà¹ƒà¸ˆ หรือไม่ว่า ต้องà¸à¸²à¸£ ปิด วอลเล็ต &lt;i&gt;%1&lt;/i&gt;?</translation>
+ </message>
+ <message>
+ <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
+ <translation type="unfinished">Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
- <translation type="unfinished">ปิดà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ทั้งหมด</translation>
+ <translation type="unfinished">ปิด วอลเล็ต ทั้งหมด</translation>
</message>
<message>
<source>Are you sure you wish to close all wallets?</source>
- <translation type="unfinished">คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¸«à¸£à¸·à¸­à¹„ม่ว่าต้องà¸à¸²à¸£à¸›à¸´à¸”à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ทั้งหมด?</translation>
+ <translation type="unfinished">คุณ à¹à¸™à¹ˆà¹ƒà¸ˆ หรือไม่ว่า ต้องà¸à¸²à¸£ ปิด วอลเล็ต ทั้งหมด?</translation>
</message>
</context>
<context>
<name>CreateWalletDialog</name>
<message>
<source>Create Wallet</source>
- <translation type="unfinished">สร้างà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">สร้าง วอลเล็ต</translation>
</message>
<message>
<source>Wallet Name</source>
- <translation type="unfinished">ชื่อà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">ชื่อ วอลเล็ต</translation>
</message>
<message>
<source>Wallet</source>
- <translation type="unfinished">à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¹€à¸‡à¸´à¸™</translation>
+ <translation type="unfinished">วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation type="unfinished">เข้ารหัส วอลเล็ต วอลเล็ต จะถูภเข้ารหัส ด้วย พาสเฟส ที่ คุณ เลือà¸</translation>
</message>
<message>
<source>Encrypt Wallet</source>
- <translation type="unfinished">เข้ารหัสà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">เข้ารหัส วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">ตัวเลือภขั้นสูง</translation>
+ </message>
+ <message>
+ <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">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</translation>
</message>
<message>
<source>Disable Private Keys</source>
- <translation type="unfinished">ปิดใช้งานà¸à¸¸à¸à¹à¸ˆà¸ªà¹ˆà¸§à¸™à¸•à¸±à¸§</translation>
+ <translation type="unfinished">ปิดใช้งาน คีย์ ส่วนตัว</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">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</translation>
</message>
<message>
<source>Make Blank Wallet</source>
- <translation type="unfinished">สร้างà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์เปล่า</translation>
+ <translation type="unfinished">ทำ วอลเล็ต ให้ว่างเปล่า</translation>
</message>
<message>
- <source>Create</source>
- <translation type="unfinished">สร้าง</translation>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">ตัวอธิบาย วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
+ <translation type="unfinished">Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first</translation>
</message>
</context>
<context>
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
- <translation type="unfinished">à¹à¸à¹‰à¹„ขที่อยู่</translation>
+ <translation type="unfinished">à¹à¸à¹‰à¹„ข à¹à¸­à¸”เดรส</translation>
</message>
<message>
<source>&amp;Label</source>
- <translation type="unfinished">&amp;ป้ายชื่อ</translation>
+ <translation type="unfinished">&amp;เลเบล</translation>
</message>
<message>
<source>The label associated with this address list entry</source>
- <translation type="unfinished">รายà¸à¸²à¸£à¹à¸ªà¸”ง ป้ายชื่อที่เà¸à¸µà¹ˆà¸¢à¸§à¸‚้องà¸à¸±à¸šà¸—ี่เà¸à¹‡à¸šà¸™à¸µà¹‰</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation type="unfinished">ที่เà¸à¹‡à¸šà¸—ี่เà¸à¸µà¹ˆà¸¢à¸§à¸‚้องà¸à¸±à¸š ที่เà¸à¹‡à¸šà¸—ี่à¹à¸ªà¸”งรายà¸à¸²à¸£à¸™à¸µà¹‰ à¸à¸²à¸£à¸›à¸£à¸±à¸šà¸›à¸£à¸¸à¸‡à¸™à¸µà¹‰à¸—ำได้สำหรับ ที่เà¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¸—ี่จะใช่ส่งเงิน เท่านั้น</translation>
+ <translation type="unfinished">รายà¸à¸²à¸£ à¹à¸ªà¸”ง เลเบล ที่ เà¸à¸µà¹ˆà¸¢à¸§à¸‚้องà¸à¸±à¸š ที่เà¸à¹‡à¸š นี้</translation>
</message>
<message>
<source>&amp;Address</source>
- <translation type="unfinished">&amp;ที่อยู่</translation>
+ <translation type="unfinished">&amp;à¹à¸­à¸”เดรส</translation>
</message>
<message>
<source>New sending address</source>
- <translation type="unfinished">ที่อยู่à¸à¸²à¸£à¸ªà¹ˆà¸‡à¹ƒà¸«à¸¡à¹ˆ</translation>
+ <translation type="unfinished">à¹à¸­à¸”เดรส à¸à¸²à¸£à¸ªà¹ˆà¸‡ ใหม่</translation>
</message>
<message>
<source>Edit receiving address</source>
- <translation type="unfinished">à¹à¸à¹‰à¹„ขที่อยู่à¸à¸²à¸£à¸£à¸±à¸š</translation>
+ <translation type="unfinished">à¹à¸à¹‰à¹„ข à¹à¸­à¸”เดรส à¸à¸²à¸£à¸£à¸±à¸š</translation>
</message>
<message>
<source>Edit sending address</source>
- <translation type="unfinished">à¹à¸à¹‰à¹„ขที่อยู่à¸à¸²à¸£à¸ªà¹ˆà¸‡</translation>
+ <translation type="unfinished">à¹à¸à¹‰à¹„ข à¹à¸­à¸”เดรส à¸à¸²à¸£à¸ªà¹ˆà¸‡</translation>
</message>
<message>
- <source>Could not unlock wallet.</source>
- <translation type="unfinished">ไม่สามารถปลดล็อคà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation type="unfinished">à¹à¸­à¸”เดรส ที่ป้อน "%1" เป็น Bitcoin à¹à¸­à¸”เดรส ที่ ไม่ ถูà¸à¸•à¹‰à¸­à¸‡</translation>
</message>
- </context>
-<context>
- <name>FreespaceChecker</name>
<message>
- <source>A new data directory will be created.</source>
- <translation type="unfinished">ไดเร็à¸à¸—อรี่ใหม่ที่ใช้เà¸à¹‡à¸šà¸‚้อมูลจะถูà¸à¸ªà¸£à¹‰à¸²à¸‡à¸‚ึ้นมา</translation>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation type="unfinished">Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address</translation>
</message>
<message>
- <source>name</source>
- <translation type="unfinished">ชื่อ</translation>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation type="unfinished">The entered address "%1" is already in the address book with label "%2"</translation>
</message>
<message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation type="unfinished">มีไดเรà¸à¸—อรีอยู่à¹à¸¥à¹‰à¸§ เพิ่ม %1 หาà¸à¸„ุณต้องà¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¹„ดเรà¸à¸—อรีใหม่ที่นี่</translation>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">ไม่สามารถปลดล็อà¸à¸§à¸­à¸¥à¹€à¸¥à¹‡à¸•à¹„ด้</translation>
</message>
<message>
- <source>Path already exists, and is not a directory.</source>
- <translation type="unfinished">มีเส้นทางอยู่à¹à¸¥à¹‰à¸§à¹à¸¥à¸°à¹„ม่ใช่ไดเรà¸à¸—อรี</translation>
+ <source>New key generation failed.</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¸„ีย์ใหม่ล้มเหลว</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation type="unfinished">ไดเร็à¸à¸—อรีข้อมูลใหม่จะถูà¸à¸ªà¸£à¹‰à¸²à¸‡à¸‚ึ้น</translation>
</message>
<message>
<source>Cannot create data directory here.</source>
- <translation type="unfinished">ไม่สามารถสร้างไดเรà¸à¸—อรีข้อมูลที่นี่</translation>
+ <translation type="unfinished">ไม่สามารถสร้างไดเร็à¸à¸—อรีข้อมูลที่นี่</translation>
</message>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>มีพื้นที่ว่าง %n GB ที่ใช้งานได้</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(ต้องà¸à¸²à¸£à¸žà¸·à¹‰à¸™à¸—ี่ %n GB )</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
<message>
- <source>%1 GB of space available</source>
- <translation type="unfinished">มีพื้นที่ว่าง %1 GB ที่ใช้งานได้</translation>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation type="unfinished">At least %1 GB of data will be stored in this directory, and it will grow over time</translation>
</message>
<message>
<source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation type="unfinished">ประมาณ %1 GB ของข้อมูลจะเà¸à¹‡à¸šà¹ƒà¸™à¹„ดเร็à¸à¸—อรี่</translation>
+ <translation type="unfinished">ข้อมูลประมาณ %1 GB จะถูà¸à¹€à¸à¹‡à¸šà¹„ว้ในไดเร็à¸à¸—อรีนี้</translation>
</message>
<message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
@@ -789,12 +1557,12 @@
</translation>
</message>
<message>
- <source>The wallet will also be stored in this directory.</source>
- <translation type="unfinished">The wallet เà¸à¹‡à¸šà¹ƒà¸§à¹‰à¹ƒà¸™à¹„ดเร็à¸à¸—อรี่</translation>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation type="unfinished">%1 จะดาวน์โหลดà¹à¸¥à¸°à¸ˆà¸±à¸”เà¸à¹‡à¸šà¸ªà¸³à¹€à¸™à¸²à¸‚องบล็อà¸à¹€à¸Šà¸™ Bitcoin</translation>
</message>
<message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation type="unfinished">ข้อผิดพลาด: ไดเร็à¸à¸—อรี่ข้อมูลที่ต้องà¸à¸²à¸£ "%1" ไม่สามารถสร้างได้</translation>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation type="unfinished"> วอลเล็ตจะถูà¸à¹€à¸à¹‡à¸šà¹ƒà¸§à¹‰à¹ƒà¸™à¹„ดเร็à¸à¸—อรีนี้เช่นà¸à¸±à¸™</translation>
</message>
<message>
<source>Error</source>
@@ -806,26 +1574,38 @@
</message>
<message>
<source>Welcome to %1.</source>
- <translation type="unfinished">ยินดีต้อนรับสู่ %1</translation>
+ <translation type="unfinished">ยินดีต้อนรับเข้าสู่ %1.</translation>
</message>
<message>
<source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
- <translation type="unfinished">นี่เป็นà¸à¸²à¸£à¸£à¸±à¸™à¹‚ปรà¹à¸à¸£à¸¡à¸„รั้งà¹à¸£à¸ ท่านสามารถเลือภว่าจะเà¸à¹‡à¸šà¸‚้อมูลไว้ที่ %1</translation>
+ <translation type="unfinished">เนื่องจาà¸à¸™à¸µà¹ˆà¹€à¸›à¹‡à¸™à¸„รั้งà¹à¸£à¸à¸—ี่โปรà¹à¸à¸£à¸¡à¹€à¸›à¸´à¸”ตัว คุณสามารถเลือà¸à¹„ด้ว่า %1 จะเà¸à¹‡à¸šà¸‚้อมูลไว้ที่ใด</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">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</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">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</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation type="unfinished">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</translation>
</message>
<message>
<source>Use the default data directory</source>
- <translation type="unfinished">ใช้ไดเรà¸à¸—อรีข้อมูลเริ่มต้น</translation>
+ <translation type="unfinished">ใช้ ไดเรà¸à¸—อรี ข้อมูล เริ่มต้น</translation>
</message>
<message>
<source>Use a custom data directory:</source>
- <translation type="unfinished">ใช้ไดเรà¸à¸—อรีข้อมูลที่à¸à¸³à¸«à¸™à¸”เอง:</translation>
+ <translation type="unfinished">ใช้ ไดเรà¸à¸—อรี ข้อมูล ที่à¸à¸³à¸«à¸™à¸”เอง:</translation>
</message>
</context>
<context>
<name>HelpMessageDialog</name>
<message>
<source>version</source>
- <translation type="unfinished">รุ่น</translation>
+ <translation type="unfinished">เวอร์ชัน</translation>
</message>
<message>
<source>About %1</source>
@@ -833,85 +1613,82 @@
</message>
<message>
<source>Command-line options</source>
- <translation type="unfinished">ตัวเลือà¸à¸šà¸£à¸£à¸—ัดคำสั่ง</translation>
+ <translation type="unfinished">ตัวเลือภCommand-line </translation>
</message>
</context>
<context>
- <name>ModalOverlay</name>
+ <name>ShutdownWindow</name>
<message>
- <source>Form</source>
- <translation type="unfinished">รูป</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation type="unfinished">ความคืบหน้า</translation>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1 à¸à¸³à¸¥à¸±à¸‡à¸–ูà¸à¸›à¸´à¸”ลง…</translation>
</message>
<message>
- <source>Hide</source>
- <translation type="unfinished">ซ่อน</translation>
- </message>
- </context>
-<context>
- <name>OpenURIDialog</name>
- <message>
- <source>Paste address from clipboard</source>
- <extracomment>Tooltip text for button that allows you to paste an address that is in your clipboard.</extracomment>
- <translation type="unfinished">วางที่อยู่จาà¸à¸„ลิปบอร์ด</translation>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation type="unfinished">อย่าปิดเครื่องคอมพิวเตอร์จนà¸à¸§à¹ˆà¸²à¸«à¸™à¹‰à¸²à¸•à¹ˆà¸²à¸‡à¸™à¸µà¹‰à¸ˆà¸°à¸«à¸²à¸¢à¹„ป</translation>
</message>
</context>
<context>
- <name>OptionsDialog</name>
+ <name>ModalOverlay</name>
<message>
- <source>Options</source>
- <translation type="unfinished">ตัวเลือà¸</translation>
+ <source>Form</source>
+ <translation type="unfinished">รูปà¹à¸šà¸š</translation>
</message>
<message>
- <source>&amp;Main</source>
- <translation type="unfinished">&amp;หลัà¸</translation>
+ <source>Number of blocks left</source>
+ <translation type="unfinished">ตัวเลข ของ บล็อภที่เหลือ</translation>
</message>
<message>
- <source>Automatically start %1 after logging in to the system.</source>
- <translation type="unfinished">เริ่มต้นอัตโนมัติ %1 หลังจาภล็อà¸à¸­à¸´à¸™ เข้าสู่ระบบà¹à¸¥à¹‰à¸§</translation>
+ <source>Unknown…</source>
+ <translation type="unfinished">ไม่รู้จัà¸â€¦</translation>
</message>
<message>
- <source>&amp;Start %1 on system login</source>
- <translation type="unfinished">&amp;เริ่ม %1 ในà¸à¸²à¸£à¸¥à¹‡à¸­à¸à¸­à¸´à¸™à¸£à¸°à¸šà¸š</translation>
+ <source>calculating…</source>
+ <translation type="unfinished">à¸à¸³à¸¥à¸±à¸‡à¸„ำนวณ…</translation>
</message>
<message>
- <source>Size of &amp;database cache</source>
- <translation type="unfinished">ขนาดของ &amp;database cache</translation>
+ <source>Last block time</source>
+ <translation type="unfinished">บล็อà¸à¹€à¸§à¸¥à¸²à¸¥à¹ˆà¸²à¸ªà¸¸à¸”</translation>
</message>
<message>
- <source>Number of script &amp;verification threads</source>
- <translation type="unfinished">จำนวนของสคริปท์ &amp;verification threads</translation>
+ <source>Progress increase per hour</source>
+ <translation type="unfinished">ความคืบหน้าเพิ่มขึ้นต่อชั่วโมง</translation>
</message>
<message>
- <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation type="unfinished">IP à¹à¸­à¸”เดส ของ proxy (เช่น IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ <source>Estimated time left until synced</source>
+ <translation type="unfinished">เวลาโดยประมาณที่เหลือจนà¸à¸§à¹ˆà¸²à¸ˆà¸°à¸‹à¸´à¸‡à¸„์</translation>
</message>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
<message>
- <source>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>
- <translation type="unfinished">มินิไมซ์à¹à¸­à¸ž à¹à¸—นà¸à¸²à¸£à¸­à¸­à¸à¸ˆà¸²à¸à¹à¸­à¸žà¸žà¸¥à¸´à¹€à¸„ชั่น เมื่อวินโดว์ได้รับà¸à¸²à¸£à¸›à¸´à¸” เมื่อเลือà¸à¸•à¸±à¸§à¹€à¸¥à¸·à¸­à¸à¸™à¸µà¹‰ à¹à¸­à¸žà¸žà¸¥à¸´à¹€à¸„ชั่น จะถูà¸à¸›à¸´à¸” à¸à¹‡à¸•à¹ˆà¸­à¹€à¸¡à¸·à¹ˆà¸­ มีà¸à¸²à¸£à¹€à¸¥à¸·à¸­à¸à¹€à¸¡à¸™à¸¹ Exit/ออà¸à¸ˆà¸²à¸à¸£à¸°à¸šà¸š เท่านั้น</translation>
+ <source>Open bitcoin URI</source>
+ <translation type="unfinished">เปิด bitcoin: URI</translation>
</message>
+ </context>
+<context>
+ <name>OptionsDialog</name>
<message>
- <source>Open Configuration File</source>
- <translation type="unfinished">เปิดไฟล์à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่า</translation>
+ <source>Options</source>
+ <translation type="unfinished">ตัวเลือà¸</translation>
</message>
<message>
- <source>Reset all client options to default.</source>
- <translation type="unfinished">รีเซต ไคลเอ็นออพชั่น à¸à¸¥à¸±à¸šà¹„ปเป็นค่าเริ่มต้น</translation>
+ <source>&amp;Main</source>
+ <translation type="unfinished">&amp;หลัà¸</translation>
</message>
<message>
- <source>&amp;Reset Options</source>
- <translation type="unfinished">&amp;รีเซต ออพชั่น</translation>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">ขนาดà¹à¸„ชà¸à¸²à¸™à¸‚้อมูลสูงสุด à¹à¸„ชที่ใหà¸à¹ˆà¸‚ึ้นสามารถนำไปสู่à¸à¸²à¸£à¸‹à¸´à¸‡à¸„์ได้เร็วยิ่งขึ้น หลังจาà¸à¸™à¸±à¹‰à¸™à¸›à¸£à¸°à¹‚ยชน์จะเด่นชัดน้อยลงสำหรับà¸à¸£à¸“ีà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¸ªà¹ˆà¸§à¸™à¹ƒà¸«à¸à¹ˆ à¸à¸²à¸£à¸¥à¸”ขนาดà¹à¸„ชจะลดà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸«à¸™à¹ˆà¸§à¸¢à¸„วามจำ มีà¸à¸²à¸£à¹à¸Šà¸£à¹Œà¸«à¸™à¹ˆà¸§à¸¢à¸„วามจำ mempool ที่ไม่ได้ใช้สำหรับà¹à¸„ชนี้</translation>
</message>
<message>
- <source>&amp;Network</source>
- <translation type="unfinished">&amp;เครือข่าย</translation>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">à¸à¸³à¸«à¸™à¸”จำนวนเธรดà¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸ªà¸„ริปต์ ค่าลบสอดคล้องà¸à¸±à¸šà¸ˆà¸³à¸™à¸§à¸™à¸„อร์ที่คุณต้องà¸à¸²à¸£à¸›à¸¥à¹ˆà¸­à¸¢à¹ƒà¸«à¹‰à¸£à¸°à¸šà¸šà¸§à¹ˆà¸²à¸‡</translation>
</message>
<message>
- <source>(0 = auto, &lt;0 = leave that many cores free)</source>
- <translation type="unfinished">(0 = อัตโนมัติ, &lt;0 = ปล่อย คอร์ อิสระ)</translation>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">สิ่งนี้ช่วยให้คุณหรือเครื่องมือของบุคคลที่สามสามารถสื่อสารà¸à¸±à¸šà¹‚หนดผ่านคำสั่งบรรทัดคำสั่งà¹à¸¥à¸° JSON-RPC</translation>
</message>
<message>
<source>Enable R&amp;PC server</source>
@@ -920,23 +1697,7 @@
</message>
<message>
<source>W&amp;allet</source>
- <translation type="unfinished">&amp;à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
- </message>
- <message>
- <source>Expert</source>
- <translation type="unfinished">ผู้เชี่ยวชาà¸</translation>
- </message>
- <message>
- <source>Enable coin &amp;control features</source>
- <translation type="unfinished">เปิดใช้ coin &amp; รูปà¹à¸šà¸šà¸à¸²à¸£à¸„วบคุม</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">หาà¸à¸—่านไม่เปิดใช้ à¸à¸²à¸£à¹ƒà¸Šà¹‰à¹€à¸‡à¸´à¸™à¸—อนที่ยังไม่ยืนยัน เงินทอนจาà¸à¸à¸²à¸£à¸—ำรายà¸à¸²à¸£à¸ˆà¸°à¹„ม่สามารถใช้ได้ จนà¸à¸§à¹ˆà¸²à¸£à¸²à¸¢à¸à¸²à¸£à¸—ี่ทำà¸à¸²à¸£ จะได้รับà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸«à¸™à¸¶à¹ˆà¸‡à¸„รั้ง à¹à¸¥à¸°à¸ˆà¸°à¸à¸£à¸°à¸—บà¸à¸²à¸£à¸„ำนวณยอดคงเหลือของท่านด้วย</translation>
- </message>
- <message>
- <source>&amp;Spend unconfirmed change</source>
- <translation type="unfinished">&amp;ใช้เงินทอนที่ยังไม่ยืนยัน</translation>
+ <translation type="unfinished">ว&amp;อลเล็ต</translation>
</message>
<message>
<source>Enable &amp;PSBT controls</source>
@@ -944,48 +1705,24 @@
<translation type="unfinished">เปิดใช้งานà¸à¸²à¸£à¸„วบคุม &amp;PSBT</translation>
</message>
<message>
- <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
- <translation type="unfinished">เปิด Bitcoin ไคล์เอ็นท์พอร์ต/client port บน router โดยอัตโนมัติ วิธีนี้ใช้ได้เมื่อ router สนับสนุน UPnP à¹à¸¥à¸°à¸ªà¸–านะเปิดใช้งาน</translation>
- </message>
- <message>
- <source>Map port using &amp;UPnP</source>
- <translation type="unfinished">จองพอร์ต โดยใช้ &amp;UPnP</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation type="unfinished">เชื่อมต่อà¸à¸±à¸š Bitcoin เน็ตเวิร์ภผ่านพร็อà¸à¸‹à¸µà¹ˆà¹à¸šà¸š SOCKS5</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation type="unfinished">&amp;เชื่อมต่อผ่าน พร็อà¸à¸‹à¸µà¹ˆ SOCKS5 (พร็อà¸à¸‹à¸µà¹ˆà¹€à¸£à¸´à¹ˆà¸¡à¸•à¹‰à¸™):</translation>
- </message>
- <message>
- <source>Proxy &amp;IP:</source>
- <translation type="unfinished">พร็อà¸à¸‹à¸µà¹ˆ &amp;IP:</translation>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">ผู้ลงนามภายนอภ(เช่น ฮาร์ดà¹à¸§à¸£à¹Œà¸§à¸­à¸¥à¹€à¸¥à¹‡à¸•)</translation>
</message>
<message>
<source>&amp;Port:</source>
- <translation type="unfinished">&amp;พอร์ต</translation>
- </message>
- <message>
- <source>Port of the proxy (e.g. 9050)</source>
- <translation type="unfinished">พอร์ตของพร็อà¸à¸‹à¸µà¹ˆ (ตัวอย่าง 9050)</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation type="unfinished">ใช้ในà¸à¸²à¸£à¹€à¸‚้าถึงอีà¸à¸à¹ˆà¸²à¸¢à¸«à¸™à¸¶à¹ˆà¸‡ peer โดย:</translation>
+ <translation type="unfinished">&amp;พอร์ต:</translation>
</message>
<message>
<source>&amp;Window</source>
- <translation type="unfinished">&amp;หน้าต่าง</translation>
+ <translation type="unfinished">&amp;วินโดว์</translation>
</message>
<message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation type="unfinished">à¹à¸ªà¸”งเฉพาะไอคอนถาดหลังจาà¸à¸¢à¹ˆà¸­à¸«à¸™à¹‰à¸²à¸•à¹ˆà¸²à¸‡</translation>
+ <source>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>
+ <translation type="unfinished">URL ของบุคคลที่สาม (เช่น เครื่องมือสำรวจà¸à¸²à¸£à¸šà¸¥à¹‡à¸­à¸) ที่ปราà¸à¸à¹ƒà¸™à¹à¸—็บธุรà¸à¸£à¸£à¸¡à¹€à¸›à¹‡à¸™à¸£à¸²à¸¢à¸à¸²à¸£à¹€à¸¡à¸™à¸¹à¸šà¸£à¸´à¸šà¸— %s ใน URL จะถูà¸à¹à¸—นที่ด้วยà¹à¸®à¸Šà¸˜à¸¸à¸£à¸à¸£à¸£à¸¡ URL หลายรายà¸à¸²à¸£à¸–ูà¸à¸„ั่นด้วยà¹à¸–บà¹à¸™à¸§à¸•à¸±à¹‰à¸‡ |</translation>
</message>
<message>
- <source>User Interface &amp;language:</source>
- <translation type="unfinished">&amp;ภาษาส่วนติดต่อผู้ใช้:</translation>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;URL ธุรà¸à¸£à¸£à¸¡à¸šà¸¸à¸„คลที่สาม</translation>
</message>
<message>
<source>&amp;OK</source>
@@ -996,9 +1733,8 @@
<translation type="unfinished">&amp;ยà¸à¹€à¸¥à¸´à¸</translation>
</message>
<message>
- <source>Configuration options</source>
- <extracomment>Window title text of pop-up box that allows opening up of configuration file.</extracomment>
- <translation type="unfinished">ตัวเลือà¸à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่า</translation>
+ <source>none</source>
+ <translation type="unfinished">ไม่มี</translation>
</message>
<message>
<source>Continue</source>
@@ -1017,68 +1753,288 @@
<name>OverviewPage</name>
<message>
<source>Form</source>
- <translation type="unfinished">รูป</translation>
+ <translation type="unfinished">รูปà¹à¸šà¸š</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation type="unfinished">พร้อมใช้งาน:</translation>
</message>
<message>
<source>Balances</source>
- <translation type="unfinished">ยอดดุล</translation>
+ <translation type="unfinished">ยอดคงเหลือ</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation type="unfinished">ทั้งหมด:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation type="unfinished">ยอดคงเหลือ ทั้งหมด ในปัจจุบัน ของคุณ</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation type="unfinished">ที่สามารถใช้จ่ายได้:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡ ล่าสุด</translation>
</message>
</context>
<context>
<name>PSBTOperationsDialog</name>
<message>
- <source>Copy to Clipboard</source>
- <translation type="unfinished">คัดลอà¸à¹„ปยังคลิปบอร์ด</translation>
+ <source>Save…</source>
+ <translation type="unfinished">บันทึà¸â€¦</translation>
+ </message>
+ <message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">ไม่สามารถลงนามอินพุตในขณะที่วอลเล็ตถูà¸à¸¥à¹‡à¸­à¸„</translation>
</message>
<message>
- <source>Close</source>
- <translation type="unfinished">ปิด</translation>
+ <source>Unknown error processing transaction.</source>
+ <translation type="unfinished">ข้อผิดพลาดที่ไม่รู้จัà¸à¸‚องà¸à¸²à¸£à¸›à¸£à¸°à¸¡à¸§à¸¥à¸œà¸¥à¸˜à¸¸à¸£à¸à¸£à¸£à¸¡</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation type="unfinished">PSBT คัดลอà¸à¹„ปยังคลิปบอร์ดà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation type="unfinished"> * ส่ง %1 ถึง %2</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation type="unfinished">จำนวน ทั้งหมด</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation type="unfinished">หรือ</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation type="unfinished">ธุรà¸à¸£à¸£à¸¡à¸¡à¸µ %1 อินพุตที่ไม่ได้ลงนาม</translation>
+ </message>
+ <message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(à¹à¸•à¹ˆà¹„ม่มีà¸à¸²à¸£à¹‚หลดวอลเล็ต)</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation type="unfinished">(à¹à¸•à¹ˆà¸§à¸­à¸¥à¹€à¸¥à¹‡à¸—นี้ไม่สามารถลงนามà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡à¹„ด้)</translation>
</message>
</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>Peer</source>
+ <extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
+ <translation type="unfinished">เพียร์</translation>
+ </message>
+ <message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">อายุ</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">ทิศทาง</translation>
</message>
<message>
+ <source>Sent</source>
+ <extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
+ <translation type="unfinished">ส่งà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <extracomment>Title of Peers Table column which indicates the total amount of network information we have received from the peer.</extracomment>
+ <translation type="unfinished">รับà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
<source>Address</source>
<extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
- <translation type="unfinished">ที่อยู่</translation>
+ <translation type="unfinished">à¹à¸­à¸”เดรส</translation>
</message>
<message>
<source>Type</source>
<extracomment>Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</extracomment>
- <translation type="unfinished">ชนิด</translation>
+ <translation type="unfinished">รูปà¹à¸šà¸š</translation>
</message>
- </context>
+ <message>
+ <source>Network</source>
+ <extracomment>Title of Peers Table column which states the network the peer connected through.</extracomment>
+ <translation type="unfinished">เครือข่าย</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <extracomment>An Inbound Connection from a Peer.</extracomment>
+ <translation type="unfinished">ขาเข้า</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <extracomment>An Outbound Connection to a Peer.</extracomment>
+ <translation type="unfinished">ขาออà¸</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
<message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">&amp;บันทึภภาพ…</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation type="unfinished">&amp;คัดลอภภาพ</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
- <translation type="unfinished">บันทึà¸à¸£à¸«à¸±à¸ª QR</translation>
+ <translation type="unfinished">บันทึภQR Code</translation>
</message>
- </context>
+ <message>
+ <source>PNG Image</source>
+ <extracomment>Expanded name of the PNG file format. See: https://en.wikipedia.org/wiki/Portable_Network_Graphics.</extracomment>
+ <translation type="unfinished">ภาพ PNG</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
<message>
+ <source>&amp;Information</source>
+ <translation type="unfinished">&amp;ข้อมูล</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation type="unfinished">ทั่วไป</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation type="unfinished">เครือข่าย</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation type="unfinished">ชื่อ</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation type="unfinished">ตัวเลข ของ connections</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation type="unfinished">บล็อà¸à¹€à¸Šà¸™</translation>
+ </message>
+ <message>
+ <source>Memory Pool</source>
+ <translation type="unfinished">พูลเมมโมรี่</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation type="unfinished">à¸à¸²à¸£à¹ƒà¸Šà¹‰à¹€à¸¡à¸¡à¹‚มรี่</translation>
+ </message>
+ <message>
<source>Wallet: </source>
- <translation type="unfinished">à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์: </translation>
+ <translation type="unfinished">วอลเล็ต: </translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation type="unfinished">(ไม่มี)</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation type="unfinished">&amp;รีเซ็ต</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation type="unfinished">รับà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation type="unfinished">ส่งà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation type="unfinished">เวอร์ชัน</translation>
</message>
<message>
<source>Last Transaction</source>
<translation type="unfinished">ธุรà¸à¸£à¸£à¸¡à¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">ไม่ว่าเราจะรีเลย์à¹à¸­à¸”เดรสปยังเพียร์นี้หรือไม่</translation>
+ </message>
+ <message>
<source>Address Relay</source>
- <translation type="unfinished">รีเลย์ที่อยู่</translation>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">รีเลย์ à¹à¸­à¸”เดรส</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">à¹à¸­à¸”เดรส ที่ประมวลผลà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">à¹à¸­à¸”เดรส จำà¸à¸±à¸”อัตรา</translation>
</message>
<message>
<source>Node window</source>
<translation type="unfinished">หน้าต่างโหนด</translation>
</message>
<message>
+ <source>Decrease font size</source>
+ <translation type="unfinished">ลด ขนาด ตัวอัà¸à¸©à¸£</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation type="unfinished">เพิ่ม ขนาด ตัวอัà¸à¸©à¸£</translation>
+ </message>
+ <message>
+ <source>Permissions</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸šà¸£à¸´à¸à¸²à¸£</translation>
+ </message>
+ <message>
+ <source>High Bandwidth</source>
+ <translation type="unfinished">à¹à¸šà¸™à¸”์วิดท์สูง</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation type="unfinished">เวลาในà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­</translation>
+ </message>
+ <message>
+ <source>Last Block</source>
+ <translation type="unfinished">Block สุดท้าย</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸ªà¹ˆà¸‡à¸¥à¹ˆà¸²à¸ªà¸¸à¸”</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸£à¸±à¸šà¸¥à¹ˆà¸²à¸ªà¸¸à¸”</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation type="unfinished">เวลาในà¸à¸²à¸£ Ping</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation type="unfinished">คอยในà¸à¸²à¸£ Ping</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation type="unfinished">วินาทีในà¸à¸²à¸£ Ping</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation type="unfinished">บล็อà¸à¹€à¸§à¸¥à¸²à¸¥à¹ˆà¸²à¸ªà¸¸à¸”</translation>
+ </message>
+ <message>
<source>&amp;Open</source>
<translation type="unfinished">&amp;เปิด</translation>
</message>
@@ -1087,24 +2043,107 @@
<translation type="unfinished">&amp;คอนโซล</translation>
</message>
<message>
+ <source>Totals</source>
+ <translation type="unfinished">ทั้งหมด</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation type="unfinished">ไฟล์บันทึà¸à¸à¸²à¸£à¸”ีบัà¸</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation type="unfinished">เข้า:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation type="unfinished">ออà¸:</translation>
+ </message>
+ <message>
+ <source>Inbound: initiated by peer</source>
+ <extracomment>Explanatory text for an inbound peer connection.</extracomment>
+ <translation type="unfinished">ขาเข้า: เริ่มต้นด้วย peer</translation>
+ </message>
+ <message>
+ <source>Outbound Full Relay: default</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</extracomment>
+ <translation type="unfinished">ขาออภFull Relay: ค่าเริ่มต้น</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;คัดลอภà¹à¸­à¸”เดรส</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation type="unfinished">&amp;หยุดเชื่อมต่อ</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation type="unfinished">1 &amp;ขั่วโมง</translation>
+ </message>
+ <message>
+ <source>1 d&amp;ay</source>
+ <translation type="unfinished">1 &amp;วัน</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation type="unfinished">1 &amp;สัปดาห์</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation type="unfinished">1 &amp;ปี</translation>
+ </message>
+ <message>
<source>&amp;Copy IP/Netmask</source>
<extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
<translation type="unfinished">&amp;คัดลอภIP/Netmask</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation type="unfinished">ดำเนินà¸à¸²à¸£à¸„ำสั่งโดยไม่มีวอลเล็ตใด ๆ</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation type="unfinished">ดำเนินà¸à¸²à¸£à¸„ำสั่งโดยใช้ "%1" วอลเล็ต</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation type="unfinished">โดยผ่าน %1</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation type="unfinished">ใช่</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation type="unfinished">ไม่</translation>
+ </message>
+ <message>
<source>To</source>
- <translation type="unfinished">ถึง</translation>
+ <translation type="unfinished">ไปยัง</translation>
</message>
<message>
<source>From</source>
<translation type="unfinished">จาà¸</translation>
</message>
- </context>
+ <message>
+ <source>Never</source>
+ <translation type="unfinished">ไม่เคย</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation type="unfinished">ไม่รู้จัà¸</translation>
+ </message>
+</context>
<context>
<name>ReceiveCoinsDialog</name>
<message>
+ <source>&amp;Amount:</source>
+ <translation type="unfinished">&amp;จำนวน:</translation>
+ </message>
+ <message>
<source>&amp;Label:</source>
- <translation type="unfinished">&amp;ป้ายชื่อ:</translation>
+ <translation type="unfinished">&amp;เลเบล:</translation>
</message>
<message>
<source>&amp;Message:</source>
@@ -1112,7 +2151,7 @@
</message>
<message>
<source>Clear</source>
- <translation type="unfinished">ล้าง</translation>
+ <translation type="unfinished">เคลียร์</translation>
</message>
<message>
<source>Show</source>
@@ -1120,22 +2159,38 @@
</message>
<message>
<source>Remove</source>
- <translation type="unfinished">เอาออà¸</translation>
+ <translation type="unfinished">นำออà¸</translation>
</message>
<message>
<source>Copy &amp;URI</source>
- <translation type="unfinished">&amp;คัดลอภURI</translation>
+ <translation type="unfinished">คัดลอภ&amp;URI</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;คัดลอภà¹à¸­à¸”เดรส</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">คัดลอภ&amp;เลเบล</translation>
+ </message>
+ <message>
+ <source>Copy &amp;message</source>
+ <translation type="unfinished">คัดลอภ&amp;ข้อความ</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">คัดลอภ&amp;จำนวน</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
- <translation type="unfinished">ไม่สามารถปลดล็อคà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">ไม่สามารถปลดล็อà¸à¸§à¸­à¸¥à¹€à¸¥à¹‡à¸•à¹„ด้</translation>
</message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
<source>Address:</source>
- <translation type="unfinished">ที่อยู่:</translation>
+ <translation type="unfinished">à¹à¸­à¸”เดรส:</translation>
</message>
<message>
<source>Amount:</source>
@@ -1143,7 +2198,7 @@
</message>
<message>
<source>Label:</source>
- <translation type="unfinished">ป้ายชื่อ:</translation>
+ <translation type="unfinished">เลเบล:</translation>
</message>
<message>
<source>Message:</source>
@@ -1151,15 +2206,31 @@
</message>
<message>
<source>Wallet:</source>
- <translation type="unfinished">à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์:</translation>
+ <translation type="unfinished">วอลเล็ต:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
- <translation type="unfinished">&amp;คัดลอภURI</translation>
+ <translation type="unfinished">คัดลอภ&amp;URI</translation>
</message>
<message>
<source>Copy &amp;Address</source>
- <translation type="unfinished">&amp;คัดลอà¸à¸—ี่อยู่</translation>
+ <translation type="unfinished">คัดลอà¸Â &amp;à¹à¸­à¸”เดรส</translation>
+ </message>
+ <message>
+ <source>&amp;Verify</source>
+ <translation type="unfinished">&amp;ตรวจสอบ</translation>
+ </message>
+ <message>
+ <source>Verify this address on e.g. a hardware wallet screen</source>
+ <translation type="unfinished">ยืนยัน à¹à¸­à¸”เดรส นี้ อยู่ใน เช่น ฮาร์ดà¹à¸§à¸£à¹Œ วอลเล็ต สà¸à¸£à¸µà¸™</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">&amp;บันทึภภาพ…</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation type="unfinished">ข้อมูà¸à¸²à¸£à¸Šà¸³à¸£à¸°à¹€à¸‡à¸´à¸™</translation>
</message>
</context>
<context>
@@ -1170,7 +2241,7 @@
</message>
<message>
<source>Label</source>
- <translation type="unfinished">ป้ายชื่อ</translation>
+ <translation type="unfinished">เลเบล</translation>
</message>
<message>
<source>Message</source>
@@ -1178,22 +2249,34 @@
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ไม่มีป้ายชื่อ)</translation>
+ <translation type="unfinished">(ไม่มีเลเบล)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation type="unfinished">(ไม่มีข้อความ)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation type="unfinished">ร้องขอà¹à¸¥à¹‰à¸§</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
<source>Send Coins</source>
- <translation type="unfinished">ส่งเหรียà¸</translation>
+ <translation type="unfinished">ส่ง คอยน์</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation type="unfinished">ทำà¸à¸²à¸£à¹€à¸¥à¸·à¸­à¸ โดยอัตโนมัติà¹à¸¥à¹‰à¸§</translation>
</message>
<message>
<source>Quantity:</source>
- <translation type="unfinished">จำนวน:</translation>
+ <translation type="unfinished">ปริมาณ:</translation>
</message>
<message>
<source>Bytes:</source>
- <translation type="unfinished">ไบต์:</translation>
+ <translation type="unfinished">ไบทส์:</translation>
</message>
<message>
<source>Amount:</source>
@@ -1205,61 +2288,164 @@
</message>
<message>
<source>After Fee:</source>
- <translation type="unfinished">ส่วนที่เหลือจาà¸à¸„่าธรรมเนียม:</translation>
+ <translation type="unfinished">หลังค่าธรรมเนียม:</translation>
</message>
<message>
<source>Change:</source>
- <translation type="unfinished">เงินทอน:</translation>
+ <translation type="unfinished">เปลี่ยน:</translation>
</message>
<message>
- <source>Hide</source>
- <translation type="unfinished">ซ่อน</translation>
+ <source>Custom change address</source>
+ <translation type="unfinished">เปลี่ยน à¹à¸­à¸”เดรส à¹à¸šà¸šà¸à¸³à¸«à¸™à¸”เอง</translation>
</message>
<message>
- <source>Recommended:</source>
- <translation type="unfinished">à¹à¸™à¸°à¸™à¸³:</translation>
+ <source>Transaction Fee:</source>
+ <translation type="unfinished">ค่าธรรมเนียม à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡:</translation>
</message>
<message>
- <source>Custom:</source>
- <translation type="unfinished">à¸à¸³à¸«à¸™à¸”เอง:</translation>
+ <source>Add &amp;Recipient</source>
+ <translation type="unfinished">เพิ่ม &amp;รายชื่อผู้รับ</translation>
</message>
<message>
<source>Dust:</source>
- <translation type="unfinished">เศษ:</translation>
+ <translation type="unfinished">ดัสท์:</translation>
+ </message>
+ <message>
+ <source>Choose…</source>
+ <translation type="unfinished">เลือà¸â€¦</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished">ล้าง &amp;ทั้งหมด</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation type="unfinished">ยอดคงเหลือ:</translation>
+ </message>
+ <message>
+ <source>S&amp;end</source>
+ <translation type="unfinished">&amp;ส่ง</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">คัดลอภปริมาณ</translation>
</message>
<message>
<source>Copy amount</source>
- <translation type="unfinished">คัดลอà¸à¸ˆà¸³à¸™à¸§à¸™à¹€à¸‡à¸´à¸™</translation>
+ <translation type="unfinished">คัดลอภจำนวน</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">คัดลอภค่าธรรมเนียม</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">คัดลอภหลัง ค่าธรรมเนียม</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">คัดลอภbytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">คัดลอภdust</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">คัดลอภchange</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation type="unfinished">%1 (%2 บล็อà¸)</translation>
+ </message>
+ <message>
+ <source>Sign on device</source>
+ <extracomment>"device" usually means a hardware wallet.</extracomment>
+ <translation type="unfinished">ลงชื่อบนอุปà¸à¸£à¸“์</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">เชื่อมต่อฮาร์ดà¹à¸§à¸£à¹Œà¸§à¸­à¸¥à¹€à¸¥à¹‡à¸•à¸‚องคุณà¸à¹ˆà¸­à¸™</translation>
</message>
<message>
<source> from wallet '%1'</source>
- <translation type="unfinished">จาà¸à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์ '%1'</translation>
+ <translation type="unfinished">จาภวอลเล็ต '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation type="unfinished">%1 ไปยัง '%2'</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation type="unfinished">%1 ไปยัง %2</translation>
+ </message>
+ <message>
+ <source>Sign failed</source>
+ <translation type="unfinished">เซ็น ล้มเหลว</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation type="unfinished">PSBT บันทึà¸</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation type="unfinished">หรือ</translation>
</message>
<message>
<source>Do you want to create this transaction?</source>
<extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
<translation type="unfinished">คุณต้องà¸à¸²à¸£à¸ªà¸£à¹‰à¸²à¸‡à¸˜à¸¸à¸£à¸à¸£à¸£à¸¡à¸™à¸µà¹‰à¸«à¸£à¸·à¸­à¹„ม่?</translation>
</message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">โปรดตรวจสอบธุรà¸à¸£à¸£à¸¡à¸‚องคุณ คุณสามารถสร้างà¹à¸¥à¸°à¸ªà¹ˆà¸‡à¸˜à¸¸à¸£à¸à¸£à¸£à¸¡à¸™à¸µà¹‰à¸«à¸£à¸·à¸­à¸ªà¸£à¹‰à¸²à¸‡à¸˜à¸¸à¸£à¸à¸£à¸£à¸¡ Bitcoin ที่ลงชื่อบางส่วน (PSBT) ซึ่งคุณสามารถบันทึà¸à¸«à¸£à¸·à¸­à¸„ัดลอà¸à¹à¸¥à¹‰à¸§à¸¥à¸‡à¸Šà¸·à¹ˆà¸­à¹€à¸‚้าใช้ เช่น วอลเล็ต %1 ออฟไลน์, หรือ PSBT-compatible hardware wallet</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
+ <translation type="unfinished">โปรดตรวจสอบธุรà¸à¸£à¸£à¸¡à¸‚องคุณ</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation type="unfinished">ค่าธรรมเนียม à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation type="unfinished">จำนวน ทั้งหมด</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation type="unfinished">ยืนยัน คอยน์ ที่ส่ง</translation>
+ </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform>คาดà¸à¸²à¸£à¸“์ว่าจะเริ่มà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¸ à¸²à¸¢à¹ƒà¸™ %n บล็อà¸</numerusform>
+ <numerusform />
</translation>
</message>
<message>
+ <source>Confirm custom change address</source>
+ <translation type="unfinished">ยืนยันà¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹à¸›à¸¥à¸‡à¹à¸­à¸”เดรสที่à¸à¸³à¸«à¸™à¸”เอง</translation>
+ </message>
+ <message>
<source>(no label)</source>
- <translation type="unfinished">(ไม่มีป้ายชื่อ)</translation>
+ <translation type="unfinished">(ไม่มีเลเบล)</translation>
</message>
</context>
<context>
<name>SendCoinsEntry</name>
<message>
- <source>&amp;Label:</source>
- <translation type="unfinished">&amp;ป้ายชื่อ:</translation>
+ <source>A&amp;mount:</source>
+ <translation type="unfinished">&amp;จำนวน:</translation>
</message>
<message>
- <source>Paste address from clipboard</source>
- <translation type="unfinished">วางที่อยู่จาà¸à¸„ลิปบอร์ด</translation>
+ <source>Pay &amp;To:</source>
+ <translation type="unfinished">ชำระ &amp;ให้:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation type="unfinished">&amp;เลเบล:</translation>
</message>
<message>
<source>Message:</source>
@@ -1276,22 +2462,46 @@
<context>
<name>SignVerifyMessageDialog</name>
<message>
- <source>Paste address from clipboard</source>
- <translation type="unfinished">วางที่อยู่จาà¸à¸„ลิปบอร์ด</translation>
+ <source>&amp;Sign Message</source>
+ <translation type="unfinished">&amp;เซ็น ข้อความ</translation>
</message>
<message>
- <source>Signature</source>
- <translation type="unfinished">ลายเซ็น</translation>
+ <source>Sign &amp;Message</source>
+ <translation type="unfinished">เซ็น &amp;ข้อความ</translation>
</message>
<message>
- <source>Sign &amp;Message</source>
- <translation type="unfinished">&amp;เซ็นข้อความ</translation>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished">ล้าง &amp;ทั้งหมด</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation type="unfinished">&amp;ตรวจสอบ ข้อความ</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation type="unfinished">ตรวจสอบ &amp;ข้อความ</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation type="unfinished">ปลดล็อควอลเล็ตถูà¸à¸¢à¸à¹€à¸¥à¸´à¸</translation>
</message>
<message>
<source>No error</source>
- <translation type="unfinished">ไม่มีข้อผิดพลาด</translation>
+ <translation type="unfinished">ไม่มี ข้อผิดพลาด</translation>
</message>
- </context>
+ <message>
+ <source>Message signed.</source>
+ <translation type="unfinished">ข้อความ เซ็นà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation type="unfinished">โปรดตรวจสอบลายเซ็นต์à¹à¸¥à¸°à¸¥à¸­à¸‡à¹ƒà¸«à¸¡à¹ˆà¸­à¸µà¸à¸„รั้ง</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation type="unfinished">ข้อความ ตรวจสอบà¹à¸¥à¹‰à¸§</translation>
+ </message>
+</context>
<context>
<name>SplashScreen</name>
<message>
@@ -1306,20 +2516,46 @@
<context>
<name>TransactionDesc</name>
<message>
- <source>Status</source>
- <translation type="unfinished">สถานะ</translation>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
+ <translation type="unfinished">ขัดà¹à¸¢à¹‰à¸‡à¸à¸±à¸šà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡à¸à¸±à¸š %1 à¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
+ <translation type="unfinished">%1 ทำà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™</translation>
</message>
<message>
<source>Date</source>
<translation type="unfinished">วันที่</translation>
</message>
<message>
+ <source>Source</source>
+ <translation type="unfinished">à¹à¸«à¸¥à¹ˆà¸‡à¸—ี่มา</translation>
+ </message>
+ <message>
<source>From</source>
<translation type="unfinished">จาà¸</translation>
</message>
<message>
+ <source>unknown</source>
+ <translation type="unfinished">ไม่ทราบ</translation>
+ </message>
+ <message>
<source>To</source>
- <translation type="unfinished">ถึง</translation>
+ <translation type="unfinished">ไปยัง</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation type="unfinished">à¹à¸­à¸”เดรส คุณเอง</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation type="unfinished">เลเบล</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation type="unfinished">เครดิต</translation>
</message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
@@ -1328,18 +2564,54 @@
</translation>
</message>
<message>
+ <source>not accepted</source>
+ <translation type="unfinished">ไม่ ยอมรับ</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation type="unfinished">เดบิต</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation type="unfinished">เดบิต ทั้งหมด</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation type="unfinished">เครดิต ทั้งหมด</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation type="unfinished">ค่าธรรมเนียม à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation type="unfinished">จำนวน สุทธิ</translation>
+ </message>
+ <message>
<source>Message</source>
<translation type="unfinished">ข้อความ</translation>
</message>
<message>
- <source>Comment</source>
- <translation type="unfinished">ความคิดเห็น</translation>
+ <source>Merchant</source>
+ <translation type="unfinished">ร้านค้า</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation type="unfinished">à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
</message>
<message>
<source>Amount</source>
<translation type="unfinished">จำนวน</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation type="unfinished">ถูà¸</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation type="unfinished">ผิด</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
@@ -1348,92 +2620,239 @@
</message>
<message>
<source>Type</source>
- <translation type="unfinished">ชนิด</translation>
+ <translation type="unfinished">รูปà¹à¸šà¸š</translation>
</message>
<message>
<source>Label</source>
- <translation type="unfinished">ป้ายชื่อ</translation>
+ <translation type="unfinished">เลเบล</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation type="unfinished">ไม่ยืนยัน</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation type="unfinished">เพิà¸à¹€à¸‰à¸¢</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation type="unfinished">รับ ด้วย</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation type="unfinished">รับ จาà¸</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation type="unfinished">ส่ง ถึง</translation>
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(ไม่มีป้ายชื่อ)</translation>
+ <translation type="unfinished">(ไม่มีเลเบล)</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation type="unfinished">ประเภท ของ à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
</message>
</context>
<context>
<name>TransactionView</name>
<message>
- <source>All</source>
- <translation type="unfinished">ทั้งหมด</translation>
+ <source>This week</source>
+ <translation type="unfinished">สัปดาห์นี้</translation>
</message>
<message>
- <source>Today</source>
- <translation type="unfinished">วันนี้</translation>
+ <source>Received with</source>
+ <translation type="unfinished">รับ ด้วย</translation>
</message>
<message>
- <source>This week</source>
- <translation type="unfinished">สัปดาห์นี้</translation>
+ <source>Sent to</source>
+ <translation type="unfinished">ส่ง ถึง</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation type="unfinished">ถึง ตัวคุณเอง</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation type="unfinished">อื่นๆ</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation type="unfinished">จำนวน ขั้นต่ำ</translation>
</message>
<message>
- <source>This month</source>
- <translation type="unfinished">เดือนนี้</translation>
+ <source>Range…</source>
+ <translation type="unfinished">ช่วง…</translation>
</message>
<message>
- <source>Last month</source>
- <translation type="unfinished">เดือนที่à¹à¸¥à¹‰à¸§</translation>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;คัดลอภà¹à¸­à¸”เดรส</translation>
</message>
<message>
- <source>This year</source>
- <translation type="unfinished">ปีนี้</translation>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">คัดลอภ&amp;เลเบล</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">คัดลอภ&amp;จำนวน</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">คัดลอภtransaction &amp;ID</translation>
+ </message>
+ <message>
+ <source>Copy &amp;raw transaction</source>
+ <translation type="unfinished">คัดลอภ&amp;raw transaction</translation>
+ </message>
+ <message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">คัดลอภfull transaction &amp;details</translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">&amp;à¹à¸ªà¸”งรายละเอียดà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
+ </message>
+ <message>
+ <source>&amp;Edit address label</source>
+ <translation type="unfinished">&amp;à¹à¸à¹‰à¹„ข à¹à¸­à¸”เดรส เลเบล</translation>
+ </message>
+ <message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">à¹à¸ªà¸”ง ใน %1</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation type="unfinished">ส่งออà¸à¸›à¸£à¸°à¸§à¸±à¸•à¸´à¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">เครื่องหมายจุลภาค (Comma) เพื่อà¹à¸¢à¸à¹„ฟล์</translation>
</message>
<message>
<source>Confirmed</source>
<translation type="unfinished">ยืนยันà¹à¸¥à¹‰à¸§</translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation type="unfinished">ดูอย่างเดียว</translation>
+ </message>
+ <message>
<source>Date</source>
<translation type="unfinished">วันที่</translation>
</message>
<message>
<source>Type</source>
- <translation type="unfinished">ชนิด</translation>
+ <translation type="unfinished">รูปà¹à¸šà¸š</translation>
</message>
<message>
<source>Label</source>
- <translation type="unfinished">ป้ายชื่อ</translation>
+ <translation type="unfinished">เลเบล</translation>
</message>
<message>
<source>Address</source>
- <translation type="unfinished">ที่อยู่</translation>
+ <translation type="unfinished">à¹à¸­à¸”เดรส</translation>
+ </message>
+ <message>
+ <source>ID</source>
+ <translation type="unfinished">ไอดี</translation>
</message>
<message>
<source>Exporting Failed</source>
<translation type="unfinished">à¸à¸²à¸£à¸ªà¹ˆà¸‡à¸­à¸­à¸à¸¥à¹‰à¸¡à¹€à¸«à¸¥à¸§</translation>
</message>
- </context>
+ <message>
+ <source>Exporting Successful</source>
+ <translation type="unfinished">ส่งออà¸à¸ªà¸³à¹€à¸£à¹‡à¸ˆ</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation type="unfinished">ช่วง:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation type="unfinished">ถึง</translation>
+ </message>
+</context>
<context>
<name>WalletFrame</name>
<message>
<source>Create a new wallet</source>
- <translation type="unfinished">สร้างà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">สร้าง วอลเล็ต ใหม่</translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished">ข้อผิดพลาด</translation>
</message>
- </context>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation type="unfinished">โหลด Transaction Data</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation type="unfinished">ธุรà¸à¸£à¸£à¸¡à¸—ี่ลงนามบางส่วน (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation type="unfinished">ไฟล์ PSBT ต้องมีขนาดเล็à¸à¸à¸§à¹ˆà¸² 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation type="unfinished">ไม่สามารถถอดรหัส PSBT</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
<source>Send Coins</source>
- <translation type="unfinished">ส่งเหรียà¸</translation>
+ <translation type="unfinished">ส่ง คอยน์</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation type="unfinished">ค่าธรรมเนียมà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡à¸—ี่เพิ่มขึ้นล้มเหลว</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <extracomment>Asks a user if they would like to manually increase the fee of a transaction that has already been created.</extracomment>
+ <translation type="unfinished">คุณต้องà¸à¸²à¸£à¹€à¸žà¸´à¹ˆà¸¡à¸„่าธรรมเนียมหรือไม่?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation type="unfinished">ค่าธรรมเนียมปัจจุบัน:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation type="unfinished">เพิ่มขึ้น:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation type="unfinished">ค่าธรรมเนียม ใหม่:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation type="unfinished">ยืนยันค่าธรรมเนียมที่เพิ่มขึ้น</translation>
+ </message>
+ <message>
+ <source>Can't draft transaction.</source>
+ <translation type="unfinished">ไม่สามารถร่างธุรà¸à¸£à¸£à¸¡à¹„ด้</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation type="unfinished">ไม่สามารถลงนามในà¸à¸²à¸£à¸—ำธุรà¸à¸£à¸£à¸¡</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation type="unfinished">ไม่สามารถทำธุรà¸à¸£à¸£à¸¡à¹„ด้</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation type="unfinished">คัดลอภPSBT à¹à¸¥à¹‰à¸§</translation>
+ <source>Can't display address</source>
+ <translation type="unfinished">ไม่สามารถ à¹à¸ªà¸”ง à¹à¸­à¸”เดรส</translation>
</message>
<message>
<source>default wallet</source>
- <translation type="unfinished">à¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์เริ่มต้น</translation>
+ <translation type="unfinished">วอลเล็ต เริ่มต้น</translation>
</message>
</context>
<context>
@@ -1448,11 +2867,24 @@
</message>
<message>
<source>Backup Wallet</source>
- <translation type="unfinished">สำรองข้อมูลà¸à¸£à¸°à¹€à¸›à¹‹à¸²à¸ªà¸•à¸²à¸‡à¸„์</translation>
+ <translation type="unfinished">à¹à¸šà¹‡à¸„อัพวอลเล็ต</translation>
+ </message>
+ <message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">ข้อมูล วอลเล็ต</translation>
</message>
<message>
<source>Backup Failed</source>
- <translation type="unfinished">à¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูลล้มเหลว</translation>
+ <translation type="unfinished">à¸à¸²à¸£à¸ªà¸³à¸£à¸­à¸‡à¸‚้อมูล ล้มเหลว</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation type="unfinished">สำรองข้อมูล สำเร็จà¹à¸¥à¹‰à¸§</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation type="unfinished">บันทึà¸à¸‚้อมูลวอลเล็ตไว้ที่ %1 เรียบร้อยà¹à¸¥à¹‰à¸§</translation>
</message>
<message>
<source>Cancel</source>
diff --git a/src/qt/locale/bitcoin_tk.ts b/src/qt/locale/bitcoin_tk.ts
new file mode 100644
index 0000000000..58395fb1a5
--- /dev/null
+++ b/src/qt/locale/bitcoin_tk.ts
@@ -0,0 +1,1577 @@
+<TS version="2.1" language="tk">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation type="unfinished">Salgyny ýa-da belligi rejelemek üçin syçanjygyň sag düwmesine basyň</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation type="unfinished">Täze salgy döret</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation type="unfinished">&amp;Täze</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation type="unfinished">Häzir saýlanan salgyny ulgamyň alyş-çalyş paneline göçür</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation type="unfinished">&amp;Göçür</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation type="unfinished">Ã&amp;ap</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">Häzir saýlanan salgyny bu sanawdan poz</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">Gözlemek üçin salgy ýa-da belligi ýaz</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Häzirki bellikdäki maglumaty faýla geçir</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;Geçir</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">&amp;Poz</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">Teňňeleriň haýsy salga iberiljekdigini saýla</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">Teňňeleriň haýsy salgydan alynjakdygyny saýla</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation type="unfinished">S&amp;aýla</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation type="unfinished">Iberýän salgylar</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation type="unfinished">Kabul edýän salgylar</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">Tölegleri ibermek üçin siziň Bitkoin salgylaryňyz şulardyr. Teňňeleri ibermezden ozal hemişe möçberi we kabul edýän salgyny barlaň.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Tölegleri kabul etmek üçin siziň Bitkoin salgylaryňyz şulardyr. Täze salgylary döretmek üçin kabul etmek bölüminde "Täze kabul ediji salgyny döret" düwmesini ulan.
+Diňe "miras" görnüşli salgylar bilen gol çekmek mümkin.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation type="unfinished">Salgyny göçür</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">&amp;Belligi göçür</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">&amp;Rejele</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation type="unfinished">Salgylar sanawyny geçir</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Otur bilen aýrylan faýl</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
+ <translation type="unfinished">Salgylar sanawyny %1 içine bellemäge çalşylanda ýalňyşlyk ýüze çykdy. Täzeden synap görüň.</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">Geçirip bolmady</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Bellik</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">Salgy</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(bellik ýok)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation type="unfinished">Parol sözlemi gepleşigi</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation type="unfinished">Parol sözlemini ýaz</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation type="unfinished">Täze parol sözlemi</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation type="unfinished">Täze parol sözlemini gaýtala</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation type="unfinished">Parol sözlemini görkez</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation type="unfinished">Gapjygy ÅŸifrle</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation type="unfinished">Bu amal üçin gapjygyň parol sözlemi bilen gapjygyňyzyň gulpuny açmagyňyz gerek.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation type="unfinished">Gapjygyň gulpuny aç</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation type="unfinished">Parol sözlemini çalyş</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation type="unfinished">Gapjygyň şifrlenmegini tassykla</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation type="unfinished">DuýduryÅŸ: Eger gapjygyňy ÅŸifrleseň we parol sözlemiňi ýitirseň, sen &lt;b&gt;ÄHLI BITKOINLERIŇI ÃITIRERSIŇ&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">Gapjygyňy şifrlemek isleýäniň çynmy?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">Gapjyk ÅŸifrlenen</translation>
+ </message>
+ <message>
+ <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">Gapjyk üçin täze parol sözlemini ýaz.&lt;br/&gt;&lt;b&gt;On ýa-da has köp tötänleýin nyşandan&lt;/b&gt; ýa-da &lt;b&gt;sekiz ýa-da has köp sözden&lt;/b&gt; ybarat parol sözlemini ulanyň.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation type="unfinished">Gapjyk üçin öňki we täze parol sözlemiňi ýaz.</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation type="unfinished">Gapjygyňy şifrlemek kompýuteriňe zyýanly programma ýokuşmak arkaly bitkoinleriň ogurlanmagyndan doly gorap bilmejekdigini ýatdan çykarma.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation type="unfinished">Åžifrlenmeli gapjyk</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation type="unfinished">Gapjygyň şifrlener.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation type="unfinished">Gapjygyň häzir şifrlenen.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation type="unfinished">WAJYP: Gapjyk faýlyň islendik ozalky ätiýaçlyk nusgalary täze emele gelen, şifrlenen gapjyk faýly bilen çalşyrylmaly. Howpsuzlyk maksady bilen, şifrlenen gapjyk faýlynyň ozalky ätiýaçlyk nusgalary täze şifrlenen gapjygy ulanyp başlan badyňyza peýdasyz bolup galar.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation type="unfinished">Gapjygy şifrläp bolmady</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation type="unfinished">Içki ýalňyşlyk sebäpli gapjygy şifrläp bolmady. Gapjygyň şifrlenmedi.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">Üpjün edilen parol sözlemleri gabat gelenok.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation type="unfinished">Gapjygyň gulpuny açyp bolmady</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation type="unfinished">Gapjygyň şifrini açmak üçin ýazylan parol sözlemi nädogry.</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished">Gapjygyň parol sözlemi üstünlikli çalşyldy.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished">Duýduryş: Caps Lock düwmesi açyk!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>Banned Until</source>
+ <translation type="unfinished">Gadagan edilen möhleti</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">Dolandyryp bolmaýan ýagdaý</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">Ãowuz ýalňyÅŸlyk ýüze çykdy. %1 indi ygtybarly dowam edip bilenok we çykar.</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">Içki ýalňyşlyk</translation>
+ </message>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">Içki ýalňyşlyk ýüze çykdy. %1 ygtybarly dowam etmäge çalyşar. Bu garaşylmadyk näsazlyk we ol barada aşakda beýan edilişi ýaly hasabat berip bolar.</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Sazlamalary deslapky ýagdaýyna getirmek isleýäňmi ýa-da hiçhili üýtgeşme girizmezden ýatyrmak?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Ãowuz ýalňyÅŸlyk ýüze çykdy. Sazlamalar faýlyna ýazmak mümkinçiliginiň bardygyny ýa-da ýokdugyny barla, bolmasa -nosettings bilen iÅŸletmäge çalyÅŸ.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation type="unfinished">ÃalňyÅŸlyk: Görkezilen maglumatlar katalogy "%1" ýok.</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation type="unfinished">ÃalňyÅŸlyk: %1 konfigurasiýa faýlyny derňäp bolanok.</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">ÃalňyÅŸlyk: %1</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 entek ygtybarly çykmady...</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Möçber</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Sazlamalar faýlyny okap bolanok</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Sazlamalar faýlyny ýazdyryp bolanok</translation>
+ </message>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>&amp;Overview</source>
+ <translation type="unfinished">&amp;Umumy syn</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation type="unfinished">Gapjygyň umumy synyny görkez</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation type="unfinished">&amp;GeleÅŸikler</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation type="unfinished">Geleşikleriň geçmişine göz aýla</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation type="unfinished">Ç&amp;yk</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation type="unfinished">Programmadan çyk</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation type="unfinished">%1 &amp;barada</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation type="unfinished">%1 barada maglumat görkez</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation type="unfinished">&amp;Qt barada</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation type="unfinished">Qt barada maglumat görkez</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation type="unfinished">%1 üçin konfigurasiýa opsiýalaryny üýtget</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Taze gapjyk döret</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Kiçelt</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">Gapjyk:</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">Ulgamyň işleýşi ýapyk.</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation type="unfinished">Proksi &lt;b&gt;işleýär&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation type="unfinished">Bitkoin salgysyna teňňeleri iber</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation type="unfinished">Gapjygyň ätiýaçlyk nusgasyny başga ýere goý</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation type="unfinished">Gapjygy şifrlemek üçin ulanylan parol sözlemini üýtget</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation type="unfinished">&amp;Iber</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation type="unfinished">&amp;Kabul edip al</translation>
+ </message>
+ <message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;Opsiýalar…</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;Gapjygy şifrle…</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">Gapjygyňa degişli hususy açarlary şifrle</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;Gapjygyň ätiýaçlyk nusgasyny sakla…</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;Parol sözlemini çalyş...</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">&amp;Habara gol çek…</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished">Bitkoin salgylarynyň eýesidigini subut etmek üçin habarlara öz Bitkoin salgylaryň bilen gol çek</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;Habary tassykla…</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">Habarlaryň görkezilen Bitkoin salgylary bilen gol çekilendigini kepillendirmek üçin habarlary tassykla</translation>
+ </message>
+ <message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">Faýldan BGÇBA &amp;ýükle…</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">&amp;URI aç…</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">Gapjygy ýap...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">Gapjyk döret...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">Ähli gapjyklary ýap...</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation type="unfinished">&amp;Faýl</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation type="unfinished">&amp;Sazlamalar</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation type="unfinished">&amp;Kömek</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation type="unfinished">Bölümler gurallar paneli</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Sözbaşylary sinhron ýagdaýa getirmek (%1%)...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Ulgam bilen utgaÅŸdyrmak...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Diskde bloklar indekslenýär...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Diskde bloklar işlenýär...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Diskde bloklar gaýtadan indekslenýär...</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">Deňdeşlere baglanylýar...</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation type="unfinished">Tölegleri sora (QR kodlary we bitkoin: URIleri döredýär)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation type="unfinished">Ulanylan iberilýän salgylaryň we bellikleriň sanawyny görkez</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation type="unfinished">Ulanylan kabul edip alýan salgylaryň we bellikleriň sanawyny görkez</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation type="unfinished">&amp;Buýruk setiri opsiýalary</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation type="unfinished">%1 galdy</translation>
+ </message>
+ <message>
+ <source>Catching up…</source>
+ <translation type="unfinished">Tutulýar...</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation type="unfinished">Soňky kabul edilen blok %1 öň döredilipdi.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation type="unfinished">Mundan soňky geleşikler entek görünmez.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">ÃalňyÅŸlyk</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation type="unfinished">Duýduryş</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation type="unfinished">Maglumat</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation type="unfinished">Döwrebap</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">Bölekleýýin gol çekilen bitkoin geleşigini ýükle</translation>
+ </message>
+ <message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">&amp;alyş-çalyş panelinden BGÇBA ýükle…</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation type="unfinished">Bölekleýin gol çekilen bitkoin geleşigini alyş-çalyş panelinden ýükle</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">Düwün penjiresi</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation type="unfinished">Düwüni zyýansyzlaşdyrma we anyklaýyş konsolyny aç</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished">&amp;Iberilýän salgylar</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished">&amp;Kabul edýän salgylar</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation type="unfinished">Bitkoin aç: URI</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation type="unfinished">Gapjygy aç</translation>
+ </message>
+ <message>
+ <source>Open a wallet</source>
+ <translation type="unfinished">Gapjyk aç</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">Gapjygy ýap</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">Ähli gapjyklary ýap</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation type="unfinished">Mümkin bolan Bitkoin buýruk setiri opsiýalarynyň sanawyny görmek üçin %1 goldaw habaryny görkez</translation>
+ </message>
+ <message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">&amp;Sanlaryň üstüni ört</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">Gözden geçir bölüminde sanlaryň üstüni ört</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">deslapky bellenen gapjyk</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation type="unfinished">Elýeterli gapjyk ýok</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Gapjygyň ady</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;Penjire</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation type="unfinished">Ulalt</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation type="unfinished">Esasy penjire</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation type="unfinished">%1 müşderi</translation>
+ </message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Gizle</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">G&amp;örkez</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Başga hereketler üçin bas.</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">Deňdeşler bölümini görkez</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">Ulgamyň işjeňligini öçür</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">Ulgamyň işjeňligini aç</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">ÃalňyÅŸlyk: %1</translation>
+ </message>
+ <message>
+ <source>Warning: %1</source>
+ <translation type="unfinished">Duýduryş: %1</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation type="unfinished">Sene: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation type="unfinished">Möçber: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation type="unfinished">Gapjyk: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation type="unfinished">Görnüş: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation type="unfinished">Bellik: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation type="unfinished">Salgy: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation type="unfinished">Iberilen geleÅŸik</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation type="unfinished">Gelýän geleşik</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation type="unfinished">HD açar döretmeklik &lt;b&gt;işjeň&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">HD açar döretmeklik &lt;b&gt;öçük&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">Hususy açar &lt;b&gt;öçük&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation type="unfinished">Gapjyk &lt;b&gt;şifrlenen&lt;/b&gt; we häzirki wagtda &lt;b&gt;gulpy açyk&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation type="unfinished">Gapjyk &lt;b&gt;şifrlenen&lt;/b&gt; we häzirki wagtda &lt;b&gt;gulply&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Original message:</source>
+ <translation type="unfinished">BaÅŸdaky habar:</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">Möçberleri görkezmek üçin ölçeg birligi. Başga ölçeg birligini saýlamak üçin bas.</translation>
+ </message>
+</context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation type="unfinished">Teňňe saýlamak</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation type="unfinished">Sany:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">Baýtlar:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Möçber:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation type="unfinished">Gatanç:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">Toz:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">Soňundan gatanç:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">Çalyş:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation type="unfinished">hemmesini saýla(ma)</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation type="unfinished">Agaç tertibi</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation type="unfinished">Sanaw tertibi</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Möçber</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation type="unfinished">Bellik bilen kabul edildi</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation type="unfinished">Salgy bilen kabul edildi</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Sene</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation type="unfinished">Tassyklamalar</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">Tassyklandy</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">Möçberi göçür</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Salgyny göçür</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Belligi göçür</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">&amp;Möçberi göçür</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Amal &amp;IDsini we çykyş indeksini göçür</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">Ulanylmadygyny g&amp;ulpla</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">Ulanylmadygynyň &amp;gulpuny aç</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">Sany göçür</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Gatanjy göçür</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Soňundan gatanjy göçür</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">Baýtlary göçür</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">Tozy göçür</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">Gaýtargyny göçür</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation type="unfinished">(%1 gulply)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation type="unfinished">hawa</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation type="unfinished">ýok</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation type="unfinished">Islendik kabul ediji häzirki toz çäginden has kiçi möçberi kabul edip alsa, bu bellik gyzyla öwrülýär.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation type="unfinished">Her giriş üçin +/- %1 satosi üýtgäp biler.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(bellik ýok)</translation>
+ </message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation type="unfinished">%1-den gaýtargy (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation type="unfinished">(gaýtargy)</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletActivity</name>
+ <message>
+ <source>Create Wallet</source>
+ <extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
+ <translation type="unfinished">Gapjyk döret</translation>
+ </message>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">&lt;b&gt;%1&lt;/b&gt; gapjyk döredilýär...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation type="unfinished">Gapjyk döredip bolmady</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation type="unfinished">Gapjyk döretmek duýduryşy</translation>
+ </message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Gol çekenleriň sanawyny görkezip bolanok</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>Open wallet failed</source>
+ <translation type="unfinished">Gapjyk açyp bolmady</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation type="unfinished">Gapjyk açmak duýduryşy</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">deslapky bellenen gapjyk</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
+ <translation type="unfinished">Gapjygy aç</translation>
+ </message>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">&lt;b&gt;%1&lt;/b&gt; gapjyk açylýar...</translation>
+ </message>
+</context>
+<context>
+ <name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">Gapjygy ýap</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation type="unfinished">&lt;i&gt;%1&lt;/i&gt; gapjygy ýapmak isleýäniňiz çynmy?</translation>
+ </message>
+ <message>
+ <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
+ <translation type="unfinished">Kesip gysgaltmaklyk işjeň bolsa, aşa uzak wagtlap gapjygyň ýapylmagy tutuş zynjyryň gaýtadan utgaşmak zerurlygyna getirip biler.</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">Ähli gapjyklary ýap</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation type="unfinished">Ähli gapjyklary ýapmak isleýäniňiz çynmy?</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletDialog</name>
+ <message>
+ <source>Create Wallet</source>
+ <translation type="unfinished">Gapjyk döret</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation type="unfinished">Gapjygyň ady</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation type="unfinished">Gapjyk</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation type="unfinished">Gapjygy şifrle. Gapjyk siziň saýlan parol sözlemi bilen şifrlener.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation type="unfinished">Gapjygy ÅŸifrle</translation>
+ </message>
+ <message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">Giňişleýin opsiýalar</translation>
+ </message>
+ <message>
+ <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">Bu gapjyk üçin hususy açarlary öçür. Hususy açarlary öçük gapjyklaryň hiçhili hususy açary bolmaz we HD esasy açary ýa-da import edilen hususy açary bolmaz. Diňe gözden geçirip bolýan gapjyklar üçin iň göwnejaýydyr.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation type="unfinished">Hususy açarlary öçür</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Boş gapjyk emele getir. Boş gapjyklaryň başda hususy açary ýa-da skripti bolmaýar. Soňra hususy açarlar ýa-da salgylar import edilip bilner ýa-da HD esasy açar bellenip bilner.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation type="unfinished">BoÅŸ gapjyk emele getir</translation>
+ </message>
+ <message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation type="unfinished">scriptPubKey dolandyryşy üçin beýan edijileri ulan</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">Beýan ediji gapjyk</translation>
+ </message>
+ <message>
+ <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
+ <translation type="unfinished">Enjam gapjygy ýaly daşyndan gol çekilýän enjamy ulan. Ilki bilen gapjygyň ileri tutmalarynda daşyndan gol çekiji skriptini sazla.</translation>
+ </message>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">Daşyndan gol çekiji</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation type="unfinished">Döret</translation>
+ </message>
+ <message>
+ <source>Compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished">Sqlite goldawsyz (beýan ediji gapjyklar üçin gerek) düzüldi</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Daşyndan gol çekmek üçin goldawsyz (daşyndan gol çekmek üçin gerek) düzüldi</translation>
+ </message>
+</context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation type="unfinished">Salgyny rejele</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation type="unfinished">&amp;Bellik</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation type="unfinished">Bu salgy sanawyndaky ýazgy bilen baglanyşykly bellik</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation type="unfinished">Bu salgy sanawyndaky ýazgy bilen baglanyşykly salgy. Bu diňe iberýän salgylar üçin üýtgedilip bilner.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation type="unfinished">&amp;Salgy</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation type="unfinished">Täze iberýän salgy</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation type="unfinished">Kabul edýän salgyny rejele</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation type="unfinished">Iberýän salgyny rejele</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation type="unfinished">Ãazylan salgy %1 ýaly Bitkoin salgysy ýok.</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation type="unfinished">%1 salgysy %2 bellikli kabul edýän salgy hökmünde eýýäm bar we şonuň üçin ony iberýän salgy hökmünde goşup bolanok.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation type="unfinished">Ãazylan %1 salgysy salgylar kitabynda %2 belligi astynda eýýäm bar.</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">Gapjygyň gulpuny açyp bolmady.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation type="unfinished">Täze açar döredip bolmady.</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation type="unfinished">Täze maglumat sanawy dörediler. </translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation type="unfinished">at</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation type="unfinished">Sanaw eýýäm bar. Bu ýerde täze sanaw döretmekçi bolsaňyz, %1 goşuň.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation type="unfinished">Ãol eýýäm bar we ol sanaw däldir.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation type="unfinished">Bu ýerde maglumat sanawyny döredip bolanok.</translation>
+ </message>
+</context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Bitcoin</source>
+ <translation type="unfinished">Bitkoin</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation type="unfinished">Bu sanawda azyndan %1 GB maglumat saklanar we ol wagtyň geçmegi bilen köpeler.</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation type="unfinished">Bu sanawda takmynan %1 GB maglumat saklanar.</translation>
+ </message>
+ <message numerus="yes">
+ <source>(sufficient to restore backups %n day(s) old)</source>
+ <extracomment>Explanatory text on the capability of the current prune target.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation type="unfinished">%1 Bitkoin blok zynjyrynyň nusgasyny ýükläp alar we göçürer.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation type="unfinished">Gapjyk hem bu sanawa saklanar.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation type="unfinished">ÃalňyÅŸlyk: Görkezilen %1 maglumat sanawyny döredip bolanok.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">ÃalňyÅŸlyk</translation>
+ </message>
+ <message>
+ <source>Welcome</source>
+ <translation type="unfinished">Hoş geldiňiz</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation type="unfinished">%1-a hoş geldiňiz.</translation>
+ </message>
+ <message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation type="unfinished">Bu programma ilkinji gezek başlandygy sebäpli, %1-nyň öz maglumatlaryny nirä saklajakdygyny saýlap bilersiň.</translation>
+ </message>
+ <message>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">Blok zynjyrynyň saklanmagyny çäklendir</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Bu sazlamany yzyna gaýtarmaklyk tutuş blok zynjyryny gaýtadan ýükläp almak zerur. Ilki bilen tutuş zynjyry ýükläp almak we soň ony kesmek has çalt bolar. Käbir giňişleýin aýratynlyklary öçürer.</translation>
+ </message>
+ <message>
+ <source> GB</source>
+ <translation type="unfinished">GB</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Bu başdaky utgaşdyrma örän çylşyrymlydyr we kompýuteriňiziň ozal üns berilmedik enjam näsazlyklaryny ýüze çykaryp biler. Her sapar %1 işledeniňizde ol säginen ýerinden ýükläp almaga dowam eder.</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation type="unfinished">Blok zynjyrynyň saklanyşyny çäklendirmegi (kesip aýyrmagy) saýlan bolsaňyz, geçmiş maglumatlary ýene-de ýüklenip alynmaly we işlenmelidir, emma diskiňiziň ulanylyşyny azaltmak üçin soňundan pozular. </translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation type="unfinished">Deslapky bellenen maglumat sanawyny ulan</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation type="unfinished">Aýratyn maglumat sanawyny ulan:</translation>
+ </message>
+</context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation type="unfinished">wersiýa</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation type="unfinished">%1 barada</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation type="unfinished">Buýruk setiri opsiýalary</translation>
+ </message>
+</context>
+<context>
+ <name>ShutdownWindow</name>
+ <message>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1 ýapylýar...</translation>
+ </message>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation type="unfinished">Bu penjire ýitýänçä kompýuteri ýapmaň.</translation>
+ </message>
+</context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation type="unfinished">Forma</translation>
+ </message>
+ <message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation type="unfinished">Soňky geleşikler entek görünmän biler, şonuň üçin gapjygyňyzdaky galyndy nädogry bolup biler. Bu maglumat aşakda beýan edilişi ýaly gapjygyňyz bitkoin tory bilen utgaşmagy tamamlanda dogry bolar.</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation type="unfinished">Entek görkezilmedik geleşikleriň täsirine düşen bitkoinleri sarp etmek synanyşygy ulgam tarapyndan kabul edilmez.</translation>
+ </message>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;Penjire</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Daşyndan gol çekmek üçin goldawsyz (daşyndan gol çekmek üçin gerek) düzüldi</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">ÃalňyÅŸlyk</translation>
+ </message>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation type="unfinished">Forma</translation>
+ </message>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>Address</source>
+ <extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
+ <translation type="unfinished">Salgy</translation>
+ </message>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">Düwün penjiresi</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;Salgyny göçür</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Salgyny göçür</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Belligi göçür</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">&amp;Möçberi göçür</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">Gapjygyň gulpuny açyp bolmady.</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Möçber:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">Gapjyk:</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Sene</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Bellik</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(bellik ýok)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Quantity:</source>
+ <translation type="unfinished">Sany:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">Baýtlar:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Möçber:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation type="unfinished">Gatanç:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">Soňundan gatanç:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">Çalyş:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">Toz:</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">Sany göçür</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">Möçberi göçür</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Gatanjy göçür</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Soňundan gatanjy göçür</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">Baýtlary göçür</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">Tozy göçür</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">Gaýtargyny göçür</translation>
+ </message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(bellik ýok)</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Sene</translation>
+ </message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Möçber</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Sene</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Bellik</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(bellik ýok)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Salgyny göçür</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Belligi göçür</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">&amp;Möçberi göçür</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">Geleşigiň &amp;ID-sini göçür</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Otur bilen aýrylan faýl</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">Tassyklandy</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Sene</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Bellik</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">Salgy</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">Geçirip bolmady</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Taze gapjyk döret</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">ÃalňyÅŸlyk</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">deslapky bellenen gapjyk</translation>
+ </message>
+</context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;Geçir</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Häzirki bellikdäki maglumaty faýla geçir</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_tl.ts b/src/qt/locale/bitcoin_tl.ts
new file mode 100644
index 0000000000..3f6c0de91c
--- /dev/null
+++ b/src/qt/locale/bitcoin_tl.ts
@@ -0,0 +1,1527 @@
+<TS version="2.1" language="tl">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation type="unfinished">I-right-click upang i-edit ang ♦address♦ o ♦label♦</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation type="unfinished">Gumawa ng bagong ♦address♦</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation type="unfinished">&amp;Bago</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation type="unfinished">Kopyahin ang pinipiling ♦address♦ sa kasalakuyan sa ♦clipboard♦ ng sistema</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation type="unfinished">Isara</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">Tanggalin ang kasalukuyang napiling ♦address♦ sa listahan</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">Ilagay ang address o tatak na hahanapin</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">I-export ang datos sa kasalukuyang ♦tab♦ sa isang file</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;I-export</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">&amp;Tanggalin</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">Piliin ang ♦address♦ kung saan ipapadala ang mga coin</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">Piliin ang ♦address♦ kung saan tatanggap ng mga coin</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation type="unfinished">&amp;Pumili</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation type="unfinished">Pinapadala ang mga ♦address♦</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation type="unfinished">Tinatanggap ang mga ♦address♦</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">Ito ang mga ♦address♦ ng ♦Bitcoin♦ mo para pagpapadala ng mga bayad. Palaging suriin mo ang halaga at address kung saan tatanggap bago magpadala ka ng mga ♦coin.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Ito ang mga address ng ♦Bitcoin♦ para sa pagtanggap ng mga baya. Gamitin ang 'Create new receiving address' na button sa receive tab para gumawa ng bagong mga address. Ang pag-sign ay posible lamang sa uri ng mga address na 'legacy'.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation type="unfinished">&amp;Kopyahin ang ♦Address♦</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">Kopyahin ang &amp;Tatak</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">&amp;I-edit</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation type="unfinished">I-Export ang Listahan ng ♦Address♦</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Kuwir hiwalay na file</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
+ <translation type="unfinished">May mali sa pagsubok na i-save ang listahan ng address sa 1%1. Pakisubukan ulit.</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">Ang pag-export ay Nabigo</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Tatak</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">♦Address♦</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(walang tatak)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation type="unfinished">♦Passphrase♦ na ♦Dialog♦</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation type="unfinished">Ilagay ang ♦passphrase♦</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation type="unfinished">Bagong ♦passphrase♦</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation type="unfinished">Ulitin ang bagong ♦passphrase♦</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation type="unfinished">Ipakita ang ♦passphrase♦</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation type="unfinished">I-encrypt ang pitaka</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation type="unfinished">Ang operasyon na ito ay nangangailangan ng iyong pitaka ♦passphrase♦ para i-unlock ang pitaka.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation type="unfinished">I-unlock ang pitaka</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation type="unfinished">Palitan ang ♦passphrase♦</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation type="unfinished">Kumpirmahin ang ♦encryption♦ ng pitaka</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation type="unfinished">Babala: IKung i-encrypt mo ang iyong pitaka at mawawala ang ♦passphrase♦, &lt;b&gt;MAWAWALA MO ANG LAHAT NG IYONG MGA BITCOIN&lt;/b&gt;!</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">Sigurado ka ba na gusto mong i-encrypt ang iyong pitaka?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">Ang pitaka ay na-encrypt na</translation>
+ </message>
+ <message>
+ <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">Ilagay ang bagong ♦passphrase♦ para sa pitaka.&lt;br/&gt;Pakigamit ang ♦passphrase♦ of &lt;b&gt;sampu o higit pa na mga ♦random♦ na mga karakter&lt;/b&gt;, o &lt;b&gt;walo o higit pang mga salita&lt;/b&gt;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation type="unfinished">Ilagay ang lumang ♦passphrase♦ at ang bagong ♦passphrase♦ para sa pitaka.</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation type="unfinished">Tandaan na ang pag-encrypt sa iyong pitaka ay hindi ganap na mapoprotektahan ang mga ♦bitcoin♦ sa pagnanakaw ng ♦malware♦ na makakahawa sa iyong kompyuter.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation type="unfinished">Ang pitaka ay i-encrypt</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation type="unfinished">Ang iyong pitaka ay mae-encrypt na.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation type="unfinished">Ang iyong pitaka ay na-encrypt na.</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation type="unfinished">MAHALAGA: Kahit anong dating mga ♦backup♦ na ginawa mo sa ♦file♦ ng pitaka mo ay dapat na mapalitan ng bagong gawang, na-encrypt na ♦file♦ ng pitaka. Para sa mga rason ng seguridad, dating mga ♦backup♦ sa hindi na-encrypt na ♦file♦ ng pitaka ay magiging walang silbi sa lalong madaling panahon na sisimulan mong gamitin ang bago, na na-encrypt na pitaka.</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation type="unfinished">Ang pag-encrypt sa pitaka ay nabigo</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation type="unfinished">Nabigo ang pag-encrypt sa pitaka dahil sa panloob na pagkakamali. Ang iyong pitaka ay hindi na-encrypt.</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">Ang mga ibinigay na mga ♦passphrase♦ ay hindi nagtugma.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation type="unfinished">Ang pag-unlock sa pitaka ay nabigo</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation type="unfinished">Ang ♦passphrase♦ na ipinasok sa ♦decryption♦ sa pitaka ay hindi tama.</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished">Ang ♦passphrase♦ ng pitaka ay matagumpay na nabago.</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished">Babala: Ang ♦Caps Lock Key♦ ay naka-on!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation type="unfinished">♦IP/Netmask♦</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation type="unfinished">Ipinagbabawal Hanggang</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">Pagbubukod sa pagtakbo papalayo </translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">Malubhang pagkakamali ay naganap. 1%1 hindi na pwedeng magpatuloy ng ligtas at ihihinto na.</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">Panloob na pagkakamali</translation>
+ </message>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">May panloob na pagkakamali ang naganap. 1%1 ay magtatangkang ituloy na ligtas. Ito ay hindi inaasahan na problema na maaaring i-ulat katulad ng pagkalarawan sa ibaba.</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Gusto mo bang i-reset ang mga ♦setting♦ sa ♦default♦ na mga ♦value♦, o itigil na hindi gumagawa ng mga pagbabago?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Isang malubhang pagkakamali ang naganap. Suriin ang mga ♦setting♦ ng ♦file♦ na ♦writable♦, o subukan na patakbuhin sa ♦-nosettings♦.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation type="unfinished">Pagkakamali: Ang natukoy na datos na ♦directory♦ "1%1" ay wala.</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation type="unfinished">Pagkakamali: Hindi ma-parse ang ♦configuration file♦: %1.</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">Pagkakamali: 1%1</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">1%1 hindi pa nag-exit ng ligtas...</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Halaga</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Ang mga ♦setting file♦ ay hindi mabasa</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Ang mga ♦settings file♦ ay hindi maisulat</translation>
+ </message>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>&amp;Overview</source>
+ <translation type="unfinished">&amp;Pangkalahatang ideya</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation type="unfinished">Ipakita ang pangkalahatang ideya ng pitaka</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation type="unfinished">&amp;Mga transaksyon</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation type="unfinished">Tignan ang kasaysayan ng transaksyon</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation type="unfinished">♦E&amp;xit</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation type="unfinished">Ihinto ang aplikasyon</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation type="unfinished">&amp;Tungkol sa %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation type="unfinished">Ipakita ang impormasyon tungkol sa %1</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation type="unfinished">Tungkol sa &amp;♦Qt♦</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation type="unfinished">Baguhin ang mga pagpipilian sa ♦configuration♦ para sa %1</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Gumawa ng bagong pitaka</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">Pitaka:</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">Na-disable ang aktibidad ng ♦network♦</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation type="unfinished">Ang paghalili ay &lt;b&gt;na-enable&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation type="unfinished">Magpadala ng mga ♦coin♦ sa ♦address♦ ng Bitcoin</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation type="unfinished">I-backup ang pitaka sa ibang lokasyon</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation type="unfinished">Palitan ang ♦passphrase♦ na ginamit para sa pag-encrypt sa pitaka</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation type="unfinished">&amp;Ipadala</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation type="unfinished">&amp;Tumanggap</translation>
+ </message>
+ <message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;Mga pagpipilian...</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;I-encrypt ang Pitaka</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">I-encrypt ang mga pribadong mga susi na nabibilang sa iyong pitaka</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;I-backup ang Pitaka...</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;Palitan ang ♦Passphrase♦...</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">Pirmahan &amp;magmensahe...</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished">Tanda na mga mensahe sa mga ♦address♦ ng iyong ♦Bitcoin♦ para patunayan na pagmamay-ari mo sila</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;Patunayan ang mensahe...</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">Patunayan ang mga mensahe para matiyak na sila ay napirmahan ng may tinukoy na mga ♦Bitcoin address♦</translation>
+ </message>
+ <message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">&amp;I-load ang PSBT mula sa ♦file♦...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">Buksan ang &amp;♦URL♦...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">Isara ang Pitaka...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">Gumawa ng Pitaka...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">Isara ang Lahat ng mga Pitaka...</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation type="unfinished">&amp;♦File♦</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation type="unfinished">Mga &amp;♦Setting♦</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation type="unfinished">&amp;Tulong</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation type="unfinished">♦Tabs toolbar♦</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">♦Syncing Headers♦ (%1%)…</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Sini-siynchronize sa ♦network♦...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Ini-index ang mga bloke sa ♦disk♦...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Pinoproseso ang mga bloke sa ♦disk♦...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Ni-rere-index ang mga bloke sa ♦disk♦</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">Kumokonekta sa mga ♦peers♦...</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation type="unfinished">Humiling ng mga bayad (gumagawa ng ♦QR codes♦ at ♦bitcoin: URIs♦)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation type="unfinished">Ipakita ang listahan ng nagamit na pagpapadalhan na mga ♦address♦ at mga tatak</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation type="unfinished">Ipakita ang listahan ng nagamit na pagtatanggapan na mga ♦address♦ at mga tatak</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation type="unfinished">&amp;♦Command-line♦ na mga pagpipilian</translation>
+ </message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation type="unfinished">%1 sa likod</translation>
+ </message>
+ <message>
+ <source>Catching up…</source>
+ <translation type="unfinished">Humahabol...</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation type="unfinished">Ang huling natanggap na bloke ay nagawa %1kanina.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation type="unfinished">Ang mga transaksyon pagkatapos nito ay hindi pa muna makikita.</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Nagkamali</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation type="unfinished">Babala</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation type="unfinished">Impormasyon</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">Ang ♦Load♦ ay Bahagyang Napirmahan na Transaksyon sa ♦Bitcoin♦</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation type="unfinished">Ang ♦Load♦ ay Bahagyang Napirmahan na Transaksyon sa ♦Bitcoin♦ mula sa ♦clipboard♦</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">♦Node window♦</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation type="unfinished">Bukas na ♦node debugging♦ at ♦diagnostic console♦</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished">&amp;Pagpapadalhan na mga ♦address♦</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished">&amp;Pagtatanggapan na mga ♦address♦</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation type="unfinished">Buksan ang ♦bitcoin: URI♦</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation type="unfinished">Buksan ang pitaka</translation>
+ </message>
+ <message>
+ <source>Open a wallet</source>
+ <translation type="unfinished">Buksan ang pitaka</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">Isarado ang pitaka</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">Isarado ang lahat na mga pitaka</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation type="unfinished">Ipakita ang %1 tumulong sa mensahe na kumuha ng listahan ng posibleng ♦Bitcoin command-line♦ na mga pagpipilian</translation>
+ </message>
+ <message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">&amp;♦Mask♦ na mga halaga</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">I-mask ang mga halaga sa loob ng ♦Overview tab♦</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">pitaka na ♦default♦</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation type="unfinished">Walang pitaka na mayroon</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Pangalan ng pitaka</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;♦Window♦</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation type="unfinished">I-zoom</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation type="unfinished">Pangunahing ♦Window♦</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation type="unfinished">%1 na kliyente</translation>
+ </message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Itago</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Mag-click para sa marami pang gagawin.</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">Ipakita ang ♦Peers tab♦</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">I-disable ang aktibidad ng ♦network♦</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">I-enable ang aktibidad ng ♦network♦</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">Pagkakamali: 1%1</translation>
+ </message>
+ <message>
+ <source>Warning: %1</source>
+ <translation type="unfinished">Babala: %1</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation type="unfinished">Petsa: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation type="unfinished">Halaga: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation type="unfinished">Pitaka: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation type="unfinished">Uri: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation type="unfinished">Tatak: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation type="unfinished">♦Address♦: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation type="unfinished">Ipinadalang transaksyon</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation type="unfinished">Paparating na transaksyon</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation type="unfinished">♦HD♦ na susi sa henerasyon ay &lt;b&gt;na-enable&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">♦HD key generation♦ ay &lt;b&gt;na-disable&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">Pribadong susi &lt;b&gt;na-disable&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation type="unfinished">Ang pitaka ay &lt;b&gt;na-encrypt&lt;/b&gt; at kasalukuyang &lt;b&gt;na-unlock&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation type="unfinished">Ang pitaka ay &lt;b&gt;na-encrypt&lt;/b&gt; at kasalukuyang &lt;b&gt;na-lock&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Original message:</source>
+ <translation type="unfinished">Orihinal na mensahe:</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">Yunit na ipakita sa mga halaga. Mag-click para pumili ng ibang yunit.</translation>
+ </message>
+</context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Coin Selection</source>
+ <translation type="unfinished">Pagpipilian ng ♦coin♦</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation type="unfinished">Dami:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">♦Bytes♦:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Halaga:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation type="unfinished">Bayad:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">Alikabok:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">Pagkatapos na Bayad:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">Sukli:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation type="unfinished">i-(un)select lahat</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation type="unfinished">♦Tree mode♦</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation type="unfinished">Listajhan na ♦mode♦</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Halaga</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation type="unfinished">Natanggap na may kasamang ♦tatak♦</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation type="unfinished">Natanggap na may ♦address♦</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Petsa</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation type="unfinished">Mga kumpirmasyon</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">Nakumpirma</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">Kopyahin ang halaga</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopyahin ang ♦address♦</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Kopyahin ang &amp;tatak</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopyahin ang &amp;halaga</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">&amp;I-lock ang hindi nagastos</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">&amp;I-unlock ang hindi nagastos</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">Kopyahin ang dami</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Bayad sa pagkopya</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Kopyahin pagkatapos ang bayad</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">Kopyahin ang ♦bytes♦</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">Kopyahin ang ♦dust♦</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">Kopyahin ang pagbabago</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation type="unfinished">(%1 naka-lock)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation type="unfinished">oo</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation type="unfinished">hindi</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation type="unfinished">Ang tatak na ito ay nagiging pula kung ang sinomang tatanggap ay tatanggap ng halaga na mas maliit sa kasalukuyang ♦dust threshold♦</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation type="unfinished">Maaaring magbago ng +/- %1♦4satoshi(s)♦ kada ♦input♦.</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(walang tatak)</translation>
+ </message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation type="unfinished">ang pagbabago ay mula sa %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation type="unfinished">(pagbabago)</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletActivity</name>
+ <message>
+ <source>Create Wallet</source>
+ <extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
+ <translation type="unfinished">Gumawa ng pitaka</translation>
+ </message>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">Paggawa ng Pitaka &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation type="unfinished">Ang paggawa ng pitaka ay nabigo</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation type="unfinished">Babala sa paggawa ng pitaka</translation>
+ </message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">Hindi mailista ang mga tagapirma</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>Open wallet failed</source>
+ <translation type="unfinished">Pagbukas ng pitaka ay nabigo</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation type="unfinished">Babala sa pagbukas ng pitaka</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">pitaka na ♦default♦</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
+ <translation type="unfinished">Buksan ang pitaka</translation>
+ </message>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">Pagbukas sa Pitaka &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+</context>
+<context>
+ <name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">Isarado ang pitaka</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation type="unfinished">Sigurado ka ba na gusto mong isarado ang pitaka &lt;i&gt;%1&lt;/i&gt;?</translation>
+ </message>
+ <message>
+ <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
+ <translation type="unfinished">Ang pagsasarod sa pitaka sa matagal ay maaaring humantong sa pag-resync ng kabuuang ♦chain♦ kung ang pagputol ay na-enable.</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">Isarado ang lahat na mga pitaka</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation type="unfinished">Sigurado ka ba na gusto mong isarado lahat ng mga pitaka?
+</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletDialog</name>
+ <message>
+ <source>Create Wallet</source>
+ <translation type="unfinished">Gumawa ng pitaka</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation type="unfinished">Pangalan ng pitaka</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation type="unfinished">Pitaka</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation type="unfinished">I-encrypt ang pitaka. Ang pitaka ay mae-encrypt na may ♦passphrase♦ ng iyong mapipili.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation type="unfinished">I-encrypt ang pitaka</translation>
+ </message>
+ <message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">Mga Pagpipilian sa pagsulong</translation>
+ </message>
+ <message>
+ <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">I-disable ang mga pribadong mga susi para sa pitaka na ito. Ang mga pitaka na may mga pribadong mga susi na na-disable ay mawawalng ng pribadong mga susi at hindi magkakaroon ng ♦HD seed♦ o mga na-import na pribadong mga susi. Ito ay perpekto lamang para sa mga ♦watch-only♦ na mga pitaka.</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation type="unfinished">I-disable ang Pribadong mga Susi</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Gumawa ng blankong pitaka. Ang blankong mga pitaka hindi muna nagkakaroon ng pribadong mga susi o mga ♦script♦. Ang pribadong mga susi at mga ♦address♦ ay pwedeng ma-import, o ang ♦HD seed♦ ay pwedeng mai-set, mamaya.</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation type="unfinished">Gumawa ng Blankong Pitaka</translation>
+ </message>
+ <message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation type="unfinished">Gumawa ng mga ♦descriptors♦ para sa pamamahala sa ♦scriptPubKey♦</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">♦Descriptor♦ na pitaka</translation>
+ </message>
+ <message>
+ <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
+ <translation type="unfinished">Gumamit ng panlabas na pagpirmang ♦device♦ katulad ng ♦hardware♦ na pitaka. I-configure ang panlabas na ♦signer script♦ sa loob ng ♦preferences♦ ng pitaka n listahan. </translation>
+ </message>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">Panlabas na ♦signer♦</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation type="unfinished">Gumawa</translation>
+ </message>
+ <message>
+ <source>Compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished">Pinagsama-sama na walang suporta ng ♦sqlite♦ (kailangan para sa ♦descriptor♦ na pitaka)</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Pinagsama-sama na walang suporta ng ♦pag-pirma♦ (kailangan para sa panlabasna pagpirma)</translation>
+ </message>
+</context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation type="unfinished">I-edit ang ♦address♦</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation type="unfinished">&amp;Tatak</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation type="unfinished">Ang tatak na nauugnay sa ♦entry♦ ng listahan ng ♦address♦</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation type="unfinished">Ang ♦address♦ na may kaugnayan sa ipinasok sa listahan ng ♦address♦. Ito ay maaari lamang ng mabago para sa pagpapadalhan na mga ♦address♦.</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation type="unfinished">&amp;♦Address♦</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation type="unfinished">Bagong pagpapadalhan na ♦address♦</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation type="unfinished">I-edit ang pagtatanggapang ♦address♦</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation type="unfinished">I-edit ang pagpapadalhan na ♦address♦</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation type="unfinished">Ang naipasok na ♦address♦ "%1" ay hindi wasto na ♦Bitcoin address♦.</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation type="unfinished">Ang ♦Address♦ "%1" ay mayroon na bilang pagtatanggapang ♦address♦ na may tatak "%2" kaya hindi na maaaring maidagdag bilang pagpapadalhan na ♦address♦.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation type="unfinished">Ang naipasok na ♦address♦ "%1" ay nasa aklat na ng ♦address♦ na may tatak "%2".</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">Hindi maaaring ma-unlock ang pitaka.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation type="unfinished">Ang Bagong susi sa ♦generation♦ ay nabigo.</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation type="unfinished">May bagong datos na ♦directory♦ ay magagawa.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation type="unfinished">pangalan</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation type="unfinished">Ang ♦directory♦ ay mayroon na. Magdagdag ng%1kung balak mong gumawa ng bagong ♦directory♦ dito.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation type="unfinished">Ang ♦path♦ ay mayroon na, at hindi ♦directory♦.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation type="unfinished">Hindi makakagawa ng datos na ♦directory♦ dito.</translation>
+ </message>
+</context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Bitcoin</source>
+ <translation type="unfinished">♦Bitcoin♦</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation type="unfinished">Hindi bababa sa %1 ng ♦GB♦ na dato ay mailalagay sa ♦directory♦, at lalaki sa paglipas ng panahon.</translation>
+ </message>
+ <message numerus="yes">
+ <source>(sufficient to restore backups %n day(s) old)</source>
+ <extracomment>Explanatory text on the capability of the current prune target.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Nagkamali</translation>
+ </message>
+ <message>
+ <source>Welcome</source>
+ <translation type="unfinished">Maligayang Pagdating</translation>
+ </message>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation type="unfinished">bersyon</translation>
+ </message>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation type="unfinished">Huwag Patayin ang inyong kompyuter hanggang mawala ang window na ito.</translation>
+ </message>
+</context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>&amp;Main</source>
+ <translation type="unfinished">&amp;♦Main♦</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation type="unfinished">&amp;Simulan %1 sa pag-login sa sistema</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation type="unfinished">Laki ng &amp;♦database cache♦</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation type="unfinished">Bilang ng ♦script♦ &amp;pagpapatunay na mga ♦threads♦</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation type="unfinished">Mga pagpipilian sa &amp;Pag-reset</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation type="unfinished">&amp;♦Network♦</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation type="unfinished">Putulan &amp;i-block ang imbakan sa</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation type="unfinished">&amp;Pitaka</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation type="unfinished">I-enable ang pag-control na mga tampok ng ♦coin♦ </translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation type="unfinished">&amp;Gumastos ng hindi nakumpirmang pagbabago</translation>
+ </message>
+ <message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">&amp;Panlabas na ♦signer script♦ na daanan</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation type="unfinished">♦Port♦ ng mapa gamit ang &amp;♦UPnP♦</translation>
+ </message>
+ <message>
+ <source>Map port using NA&amp;T-PMP</source>
+ <translation type="unfinished">♦Port♦ ng mapa gamit ang NA&amp;T-PMP</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation type="unfinished">Pahintulutan ang paparating na mga &amp;koneksyon</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation type="unfinished">&amp;Kumonketa sa pamamagitan ng ♦SOCKS5 proxy (default proxy)♦:</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;♦Window♦</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Pinagsama-sama na walang suporta ng ♦pag-pirma♦ (kailangan para sa panlabasna pagpirma)</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Nagkamali</translation>
+ </message>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>Address</source>
+ <extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
+ <translation type="unfinished">♦Address♦</translation>
+ </message>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">♦Node window♦</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;Kopyahin ang ♦address♦</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopyahin ang ♦address♦</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Kopyahin ang &amp;tatak</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopyahin ang &amp;halaga</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">Hindi maaaring ma-unlock ang pitaka.</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Halaga:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">Pitaka:</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Petsa</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Tatak</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(walang tatak)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Quantity:</source>
+ <translation type="unfinished">Dami:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">♦Bytes♦:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">Halaga:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation type="unfinished">Bayad:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">Pagkatapos na Bayad:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">Sukli:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">Alikabok:</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">Kopyahin ang dami</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">Kopyahin ang halaga</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Bayad sa pagkopya</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Kopyahin pagkatapos ang bayad</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">Kopyahin ang ♦bytes♦</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">Kopyahin ang ♦dust♦</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">Kopyahin ang pagbabago</translation>
+ </message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(walang tatak)</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Petsa</translation>
+ </message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">Halaga</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Petsa</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Tatak</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(walang tatak)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;Kopyahin ang ♦address♦</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">&amp;Kopyahin ang &amp;tatak</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">Kopyahin ang &amp;halaga</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">Kopyahin ang transaksyon ng &amp;♦ID♦</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Kuwir hiwalay na file</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">Nakumpirma</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">Petsa</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">Tatak</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">♦Address♦</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">Ang pag-export ay Nabigo</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">Gumawa ng bagong pitaka</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">Nagkamali</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">pitaka na ♦default♦</translation>
+ </message>
+</context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;I-export</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">I-export ang datos sa kasalukuyang ♦tab♦ sa isang file</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts
index c4c7d290a6..f7c86ecd4f 100644
--- a/src/qt/locale/bitcoin_tr.ts
+++ b/src/qt/locale/bitcoin_tr.ts
@@ -150,7 +150,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation type="unfinished">Bu işlemi yapabilmek için cüzdan parolanızı girmeniz gerekmektedir
+ <translation type="unfinished">kilidi açmakparolaBu işlemi yapabilmek için cüzdan parolanızı girmeniz gerekmektedir
Cüzdan kilidini aç.</translation>
</message>
<message>
@@ -248,6 +248,10 @@ Cüzdan kilidini aç.</translation>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">%1 ayar dosyası bozuk veya geçersiz olabilir.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Sızıntı istisnası</translation>
</message>
@@ -360,7 +364,7 @@ Cüzdan kilidini aç.</translation>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform>%ngün</numerusform>
+ <numerusform>%n gün</numerusform>
</translation>
</message>
<message numerus="yes">
@@ -411,14 +415,18 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">%s dosyasının okunması sırasında bir hata meydana geldi! Tüm anahtarlar doğru bir şekilde okundu, ancak işlem verileri ya da adres defteri ögeleri hatalı veya eksik olabilir.</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Hata: İçeri gelen bağlantıların dinlenmesi başarısız oldu (dinleme %s hatasını verdi)</translation>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">%s okuma hatası! İşlem verileri eksik veya yanlış olabilir. Cüzdan yeniden taranıyor.</translation>
</message>
<message>
<source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
<translation type="unfinished">-maxtxfee=&lt;tutar&gt; için geçersiz tutar: '%s' (Sıkışmış işlemleri önlemek için en az %s değerinde en düşük aktarım ücretine eşit olmalıdır)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">Geçersiz veya bozuk peers.dat (%s). Bunun bir hata olduğunu düşünüyorsanız, lütfen %s'e bildirin. Geçici bir çözüm olarak, bir sonraki başlangıçta yeni bir dosya oluşturmak için dosyayı (%s) yoldan çekebilirsiniz (yeniden adlandırabilir, taşıyabilir veya silebilirsiniz).</translation>
+ </message>
+ <message>
<source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
<translation type="unfinished">Lütfen bilgisayarınızın tarih ve saatinin doğruluğunu kontrol edin. Hata varsa %s doğru çalışmayacaktır.</translation>
</message>
@@ -439,6 +447,10 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Blok veritabanı gelecekten gibi görünen bir blok içermektedir. Bu, bilgisayarınızın saat ve tarihinin yanlış ayarlanmış olmasından kaynaklanabilir. Blok veritabanını sadece bilgisayarınızın tarih ve saatinin doğru olduğundan eminseniz yeniden derleyin.</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">Blok dizini db, eski bir 'txindex' içerir. Dolu disk alanını temizlemek için full -reindex çalıştırın, aksi takdirde bu hatayı yok sayın. Bu hata mesajı tekrar görüntülenmeyecek.</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">Bu işlem, tutar düşüldükten sonra göndermek için çok düşük</translation>
</message>
@@ -475,10 +487,34 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Çözümlenemedi - %s adres: '%s'</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">-dnsseed false olarak ayarlanırken -forcednsseed true olarak ayarlanamıyor.</translation>
+ </message>
+ <message>
<source>Cannot write to data directory '%s'; check permissions.</source>
<translation type="unfinished">Veriler '%s' klasörüne yazılamıyor ; yetkilendirmeyi kontrol edin.</translation>
</message>
<message>
+ <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">Önceki bir sürüm tarafından başlatılan -txindex yükseltmesi tamamlanamaz. Önceki sürümle yeniden başlatın veya full -reindex çalıştırın.</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s, %u bağlantı noktasında dinleme isteğinde bulunur. Bu bağlantı noktası "kötü" olarak kabul edilir ve bu nedenle, herhangi bir Bitcoin Core eşinin ona bağlanması olası değildir. Ayrıntılar ve tam liste için doc/p2p-bad-ports.md'ye bakın.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Belirli bağlantılar sağlayamaz ve aynı anda addrman'ın giden bağlantıları bulmasını sağlayamaz.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">%s yüklenirken hata oluştu: Harici imzalayan cüzdanı derlenmiş harici imzalayan desteği olmadan yükleniyor</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Geçersiz peers.dat dosyası yeniden adlandırılamadı. Lütfen taşıyın veya silin ve tekrar deneyin.</translation>
+ </message>
+ <message>
<source>Copyright (C) %i-%i</source>
<translation type="unfinished">Telif Hakkı (C) %i-%i</translation>
</message>
@@ -531,10 +567,6 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Veritabanı okuma hatası, program kapatılıyor.</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Zincirdurumu veritabanı yükseltme hatası</translation>
- </message>
- <message>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation type="unfinished">Herhangi bir portun dinlenmesi başarısız oldu. Bunu istiyorsanız -listen=0 seçeneğini kullanınız.</translation>
</message>
@@ -559,6 +591,10 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Başlatma sınaması başarısız oldu. %s kapatılıyor.</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Girdi bulunamadı veya zaten harcandı</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">Yetersiz bakiye</translation>
</message>
@@ -611,6 +647,10 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Eksik tutar</translation>
</message>
<message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">İşlem boyutunu tahmin etmek için çözümleme verileri eksik</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">-whitebind: '%s' ile bir port belirtilmesi lazımdır</translation>
</message>
@@ -687,6 +727,10 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">İşlem tutarı negatif olmamalıdır.</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">İşlem değişikliği çıktı endeksi aralık dışında</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">İşlem çok uzun bir mempool zincirine sahip</translation>
</message>
@@ -695,6 +739,10 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">İşlem en az bir adet alıcıya sahip olmalı.</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">İşlemin bir değişiklik adresine ihtiyacı var, ancak bunu oluşturamıyoruz.</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">İşlem çok büyük</translation>
</message>
@@ -715,6 +763,10 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Anahtarlar oluşturulamıyor</translation>
</message>
<message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">-maxuploadtarget ayrıştırılamıyor: '%s'</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">HTTP sunucusu başlatılamadı. Ayrıntılar için debug.log dosyasına bakınız.</translation>
</message>
@@ -731,10 +783,6 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Desteklenmeyen günlük kategorisi %s=%s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">UTXO veritabanı yükseltiliyor</translation>
- </message>
- <message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">Kullanıcı Aracı açıklaması (%s) güvensiz karakterler içermektedir.</translation>
</message>
@@ -941,7 +989,7 @@ Cüzdan kilidini aç.</translation>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>İşlem geçmişinin %n bloğu işlendi.</numerusform>
</translation>
</message>
<message>
@@ -1017,6 +1065,16 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Cüzdan kapat</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Cüzdanı Geri Yükle...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Yedekleme dosyasından bir cüzdanı geri yükle</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Tüm cüzdanları kapat</translation>
</message>
@@ -1037,6 +1095,26 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Erişilebilir cüzdan yok</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Cüzdan Verisi</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Cüzdan Yedeği Yükle</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Cüzdanı Geri Yükle</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Cüzdan İsmi</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Pencere</translation>
</message>
@@ -1169,10 +1247,6 @@ Cüzdan kilidini aç.</translation>
<context>
<name>CoinControlDialog</name>
<message>
- <source>Coin Selection</source>
- <translation type="unfinished">Koin Seçimi</translation>
- </message>
- <message>
<source>Quantity:</source>
<translation type="unfinished">Miktar</translation>
</message>
@@ -1333,7 +1407,11 @@ Cüzdan kilidini aç.</translation>
<source>Create wallet warning</source>
<translation type="unfinished">Cüzdan oluşturma uyarısı</translation>
</message>
- </context>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Çok fazla harici imzalayan bulundu</translation>
+ </message>
+</context>
<context>
<name>LoadWalletsActivity</name>
<message>
@@ -1373,6 +1451,24 @@ Cüzdan kilidini aç.</translation>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Cüzdanı Geri Yükle</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Cüzdan geri yüklenemedi</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Cüzdan uyarısını geri yükle</translation>
+ </message>
+ </context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1522,6 +1618,24 @@ Cüzdan kilidini aç.</translation>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">Bu dizinde en az %1 GB veri depolanacak ve zamanla büyüyecek.</translation>
@@ -1745,10 +1859,25 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Bu, sizin veya bir üçüncü taraf aracının komut satırı ve JSON-RPC komutları aracılığıyla düğümle iletişim kurmasına olanak tanır.</translation>
</message>
<message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">R&amp;PC sunucusunu etkinleÅŸtir</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">&amp;Cüzdan</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Tutardan çıkarma ücretinin varsayılan olarak ayarlanıp ayarlanmayacağı.</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Varsayılan olarak ücreti tutardan düş</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">GeliÅŸmiÅŸ</translation>
</message>
@@ -1765,6 +1894,16 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">&amp; Onaylanmamış bozuk parayı harcayın</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">PSBT kontrollerini etkinleÅŸtir</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">PSBT kontrollerinin gösterilip gösterilmeyeceği.</translation>
+ </message>
+ <message>
<source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
<translation type="unfinished">Yönlendiricide Bitcoin istemci portlarını otomatik olarak açar. Bu, sadece yönlendiricinizin UPnP desteği bulunuyorsa ve etkinse çalışabilir.</translation>
</message>
@@ -1837,6 +1976,10 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Bitcoin gönderildiğinde arayüzde gösterilecek varsayılan alt birimi seçiniz.</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">İşlemler sekmesinde bağlam menüsü unsurları olarak görünen üçüncü taraf bağlantıları (mesela bir blok tarayıcısı). URL'deki %s, işlem hash değeri ile değiştirilecektir. Birden çok bağlantılar düşey çubuklar | ile ayrılacaktır.</translation>
+ </message>
+ <message>
<source>&amp;Third-party transaction URLs</source>
<translation type="unfinished">&amp;Üçüncü parti işlem URL'leri</translation>
</message>
@@ -1870,14 +2013,17 @@ Cüzdan kilidini aç.</translation>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">Seçenekleri sıfırlamayı onayla</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Değişikliklerin uygulanması için istemcinin yeniden başlatılması lazımdır.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">İstemci kapanacaktır. Devam etmek istiyor musunuz?</translation>
</message>
<message>
@@ -2129,6 +2275,11 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Gecikme</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">YaÅŸ</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">Yönlendirme</translation>
@@ -2308,14 +2459,26 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Son Ä°ÅŸlem</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Adresleri bu eÅŸe iletip iletemeyeceÄŸimiz.</translation>
+ </message>
+ <message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Adres Aktarımı</translation>
</message>
<message>
<source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
<translation type="unfinished">Adresler Ä°ÅŸlendi</translation>
</message>
<message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Adresler Oran-Sınırlı</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">Kullanıcı Yazılımı</translation>
</message>
@@ -2851,6 +3014,11 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Bu iÅŸlemi oluÅŸturmak ister misiniz?</translation>
</message>
<message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Lütfen işleminizi gözden geçirin. Bu işlemi oluşturabilir ve gönderebilir veya örneğin çevrimdışı bir %1 cüzdanı veya PSBT uyumlu bir donanım cüzdanı gibi kaydedebileceğiniz veya kopyalayabileceğiniz ve ardından imzalayabileceğiniz bir Kısmen İmzalı Bitcoin İşlemi (PSBT) oluşturabilirsiniz.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">Lütfen işleminizi gözden geçirin.</translation>
@@ -2891,10 +3059,6 @@ Cüzdan kilidini aç.</translation>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">%1 tutarından yüksek bir ücret saçma derecede yüksek bir ücret olarak kabul edilir.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Ödeme talebinin geçerlilik süresi bitti.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2969,14 +3133,6 @@ Cüzdan kilidini aç.</translation>
<translation type="unfinished">Ä°leti:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Bu, kimliği doğrulanmamış bir ödeme talebidir.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Bu, kimliği doğrulanmış bir ödeme talebidir.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Kullanılmış adres listesine eklemek için bu adrese bir etiket girin</translation>
</message>
@@ -2984,14 +3140,6 @@ Cüzdan kilidini aç.</translation>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">Referans için bitcoin: URI'siyle iliştirilmiş işlemle birlikte depolanacak bir ileti. Not: Bu mesaj Bitcoin ağı üzerinden gönderilmeyecektir.</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Şu adrese öde:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Not:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3158,30 +3306,22 @@ Cüzdan kilidini aç.</translation>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">%1 doğrulamalı bir işlem ile çelişti</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/doğrulanmamış, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">bellek alanında</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">bellek alanında değil</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">terk edilmiÅŸ</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/doğrulanmadı</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 doÄŸrulama</translation>
</message>
<message>
diff --git a/src/qt/locale/bitcoin_ug.ts b/src/qt/locale/bitcoin_ug.ts
index 08f03f97ee..a90995225b 100644
--- a/src/qt/locale/bitcoin_ug.ts
+++ b/src/qt/locale/bitcoin_ug.ts
@@ -193,6 +193,27 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts
index c1053370a2..88b519b2b3 100644
--- a/src/qt/locale/bitcoin_uk.ts
+++ b/src/qt/locale/bitcoin_uk.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">Клацніть правою кнопкою миші Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð´Ñ€ÐµÑи або мітки</translation>
+ <translation type="unfinished">Клацніть правою кнопкою миші, щоб змінити адреÑу або мітку</translation>
</message>
<message>
<source>Create a new address</source>
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation type="unfinished">Копіювати виділену адреÑу в буфер обміну</translation>
+ <translation type="unfinished">Скопіюйте поточну вибрану адреÑу в ÑиÑтемний буфер обміну</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -27,19 +27,19 @@
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished">Вилучити вибрану адреÑу з переліку</translation>
+ <translation type="unfinished">Видалити поточну вибрану адреÑу зі ÑпиÑку </translation>
</message>
<message>
<source>Enter address or label to search</source>
- <translation type="unfinished">Введіть адреÑу чи мітку Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ</translation>
+ <translation type="unfinished">Введіть адреÑу або мітку Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation type="unfinished">ЕкÑпортувати дані з поточної вкладки в файл</translation>
+ <translation type="unfinished">ЕкÑпортувати дані з поточної вкладки у файл</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">&amp;ЭкÑпорт</translation>
+ <translation type="unfinished">&amp;ЕкÑпортувати</translation>
</message>
<message>
<source>&amp;Delete</source>
@@ -67,7 +67,7 @@
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation type="unfinished">Це ваші адреÑи Bitcoin Ð´Ð»Ñ Ð½Ð°Ð´ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¿Ð»Ð°Ñ‚ÐµÐ¶Ñ–Ð². Завжди перевірÑйте Ñуму та адреÑу одержувача перед відправленнÑм монет.</translation>
+ <translation type="unfinished">Це ваші біткоїн-адреÑи Ð´Ð»Ñ Ð½Ð°Ð´ÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð¿Ð»Ð°Ñ‚ÐµÐ¶Ñ–Ð². Завжди перевірÑйте Ñуму та адреÑу одержувача перед відправленнÑм монет.</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
@@ -246,12 +246,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Файл параметрів %1 можу бути пошкоджений або недійÑний.</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">Ðебажана винÑткова ÑитуаціÑ</translation>
</message>
<message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
- <translation type="unfinished">СталаÑÑ ÐºÑ€Ð¸Ñ‚Ð¸Ñ‡Ð½Ð° помилка. %1 більше не може продовжувати безпечно Ñ– завершить роботу.</translation>
+ <translation type="unfinished">СталаÑÑ Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð° помилка. %1 більше не може продовжувати безпечно Ñ– завершить роботу.</translation>
</message>
<message>
<source>Internal error</source>
@@ -259,7 +263,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
- <translation type="unfinished">Виникла Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. %1 Ñпробує безпечно продовжити роботу. Можете повідомити про цю неочікувану помилку, Ñк це опиÑано нижче.</translation>
+ <translation type="unfinished">Виникла Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. %1 Ñпробує безпечно продовжити роботу. Це неочікувана помилка, про Ñку можливо повідомити, Ñк це опиÑано нижче.</translation>
</message>
</context>
<context>
@@ -272,7 +276,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
<extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
- <translation type="unfinished">СталаÑÑ ÐºÑ€Ð¸Ñ‚Ð¸Ñ‡Ð½Ð° помилка. Перевірте, чи файл налаштувань доÑтупний Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу, або Ñпробуйте запуÑтити з -nosettings.</translation>
+ <translation type="unfinished">СталаÑÑ ÐºÑ€Ð¸Ñ‚Ð¸Ñ‡Ð½Ð° помилка. Перевірте, чи файл параметрів доÑтупний Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу, або Ñпробуйте запуÑтити з -nosettings.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" does not exist.</source>
@@ -446,11 +450,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>bitcoin-core</name>
<message>
<source>Settings file could not be read</source>
- <translation type="unfinished">Ðе вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл налаштувань</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл параметрів</translation>
</message>
<message>
<source>Settings file could not be written</source>
- <translation type="unfinished">Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл налаштувань</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл параметрів</translation>
</message>
<message>
<source>The %s developers</source>
@@ -458,7 +462,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
- <translation type="unfinished">%s пошкоджено. Спробуйте ÑкориÑтатиÑÑ Ñ–Ð½Ñтрументом Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ bitcoin-wallet Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¾Ñ— копії.</translation>
+ <translation type="unfinished">%s пошкоджено. Спробуйте ÑкориÑтатиÑÑ Ñ–Ð½Ñтрументом Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ bitcoin-wallet Ð´Ð»Ñ Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð¾Ñ— копії.</translation>
</message>
<message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
@@ -505,10 +509,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Помилка: ЗаÑтарілі гаманці підтримують тільки адреÑи типів "legacy", "p2sh-segwit" та "bech32"</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ñ‚Ð¸ проÑÐ»ÑƒÑ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ…Ñ–Ð´Ð½Ð¸Ñ… підключень (listen повернув помилку: %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">Оцінка коміÑÑ–Ñ— не вдалаÑÑ. Fallbackfee вимкнено. Зачекайте кілька блоків або ввімкніть -fallbackfee.</translation>
</message>
@@ -550,11 +550,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
- <translation type="unfinished">Ð’Ñтановлений розмір ланцюжка блоків Ñ” замалим (меншим за %d МіБ). ВикориÑтовуйте більший розмір.</translation>
+ <translation type="unfinished">Ð’Ñтановлений розмір Ñкороченого блокчейна Ñ” замалим (меншим за %d МіБ). ВикориÑтовуйте більший розмір.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">Режим Ñкороченого блокчейна неÑуміÑний з -reindex-chainstate. ВикориÑтовуйте натоміÑÑ‚ÑŒ повний -reindex.</translation>
</message>
<message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
- <translation type="unfinished">ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ ÑкороченнÑ: оÑÑ‚Ð°Ð½Ð½Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð²Ð¼Ñ–Ñту гаманцю не обмежуєтьÑÑ Ð´Ñ–Ñми над Ñкороченими даними. Вам необхідно зробити повторну індекÑацію -reindex (заново завантажити веÑÑŒ блокчейн, Ñкщо викориÑтовуєтьÑÑ ÑкороченнÑ)</translation>
+ <translation type="unfinished">Скорочений блокчейн: оÑÑ‚Ð°Ð½Ð½Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ Ð²Ð¸Ñ…Ð¾Ð´Ð¸Ñ‚ÑŒ за межі Ñкорочених даних. Потрібно перезапуÑтити з -reindex (заново завантажити веÑÑŒ блокчейн, Ñкщо викориÑтовуєтьÑÑ ÑкороченнÑ)</translation>
</message>
<message>
<source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
@@ -598,13 +602,21 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
- <translation type="unfinished">Ðеможливо відтворити блоки. Вам потрібно буде перебудувати базу даних, викориÑтовуючи -reindex-chainstate.</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð²Ñ–Ð´Ñ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ блоки. Вам потрібно буде перебудувати базу даних, викориÑтовуючи -reindex-chainstate.</translation>
</message>
<message>
<source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
<translation type="unfinished">Вказано невідомий формат "%s" файлу гаманцÑ. Укажіть "bdb" або "sqlite".</translation>
</message>
<message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">ВиÑвлено неÑуміÑний формат бази даних Ñтану блокчейна. ПерезапуÑÑ‚Ñ–Ñ‚ÑŒ з -reindex-chainstate. Це перебудує базу даних Ñтану блокчейна.</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Гаманець уÑпішно Ñтворено. Підтримка гаманців заÑтарілого типу припинÑєтьÑÑ, Ñ– можливіÑÑ‚ÑŒ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð°ÐºÐ¸Ñ… гаманців буде видалена.</translation>
+ </message>
+ <message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
<translation type="unfinished">ПопередженнÑ: Формат "%s" файлу дампа Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ Ð½Ðµ збігаєтьÑÑ Ð· форматом "%s", що зазначений у командному Ñ€Ñдку.</translation>
</message>
@@ -622,7 +634,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
- <translation type="unfinished">Вам необхідно перебудувати базу даних з викориÑтаннÑм -reindex Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð½Ð¾Ð³Ð¾ ланцюжка блоків.</translation>
+ <translation type="unfinished">Вам необхідно перебудувати базу даних з викориÑтаннÑм -reindex Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð½Ð¾Ð³Ð¾ блокчейна.</translation>
</message>
<message>
<source>%s is set very high!</source>
@@ -657,6 +669,94 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ -txindex, що було почате попередньою верÑією, не вдалоÑÑ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚Ð¸. ПерезапуÑтить попередню верÑÑ–ÑŽ або виконайте повний -reindex.</translation>
</message>
<message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s запитує проÑÐ»ÑƒÑ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñ€Ñ‚Ñƒ %u . Цей порт вважаєтьÑÑ "поганим", Ñ– тому малоймовірно, що будь-Ñкі інші вузли Bitcoin Core підключатьÑÑ Ð´Ð¾ нього. ДивітьÑÑ doc/p2p-bad-ports.md Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´ÐµÑ‚Ð°Ð»ÑŒÐ½Ð¾Ñ— інформації та повного ÑпиÑку.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Параметр -reindex-chainstate неÑуміÑний з -blockfilterindex. ТимчаÑово вимкніть blockfilterindex під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ -reindex-chainstate, або замінить -reindex-chainstate на -reindex Ð´Ð»Ñ Ð¿Ð¾Ð²Ð½Ð¾Ñ— перебудови вÑÑ–Ñ… індекÑів.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Параметр -reindex-chainstate неÑуміÑний з -coinstatsindex. ТимчаÑово вимкніть coinstatsindex під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ -reindex-chainstate, або замінить -reindex-chainstate на -reindex Ð´Ð»Ñ Ð¿Ð¾Ð²Ð½Ð¾Ñ— перебудови вÑÑ–Ñ… індекÑів.</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">Параметр -reindex-chainstate неÑуміÑний з -txindex. ТимчаÑово вимкніть txindex під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ -reindex-chainstate, або замінить -reindex-chainstate на -reindex Ð´Ð»Ñ Ð¿Ð¾Ð²Ð½Ð¾Ñ— перебудови вÑÑ–Ñ… індекÑів.</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Блокчейн, що вважаєтьÑÑ Ð´Ñ–Ð¹Ñним: оÑÑ‚Ð°Ð½Ð½Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ Ð²Ð¸Ñ…Ð¾Ð´Ð¸Ñ‚ÑŒ за межі доÑтупних даних про блоки. Зачекайте, доки фонова перевірка блокчейна завантажить більше блоків.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð²Ñтановити визначені з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ– одночаÑно викориÑтовувати addrman Ð´Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð¸Ñ…Ñ–Ð´Ð½Ð¸Ñ… з'єднань.</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ %s: Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ Ð·Ñ– зовнішнім підпиÑувачем, але Ñкомпільовано без підтримки зовнішнього підпиÑуваннÑ</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Помилка: Дані адреÑної книги в гаманці не можна ідентифікувати Ñк належні до перенеÑених гаманців</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">Помилка: Ідентичні деÑкриптори Ñтворено під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ½ÐµÑеннÑ. Можливо, гаманець пошкоджено.</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">Помилка: Транзакцію %s в гаманці не можна ідентифікувати Ñк належну до перенеÑених гаманців</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ñтворити деÑкриптори Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ заÑтарілого гаманцÑ. Спочатку переконайтеÑÑ, що гаманець розблоковано.</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ñ‚Ð¸ недійÑний файл peers.dat. Будь лаÑка, переміÑÑ‚Ñ–Ñ‚ÑŒ його та повторіть Ñпробу </translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">ÐеÑуміÑні параметри: чітко вказано -dnsseed=1, але -onlynet заборонÑÑ” IPv4/IPv6 з'єднаннÑ</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">Вихідні з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ñ– мережею Tor (-onlynet=onion), але прокÑÑ–-Ñервер Ð´Ð»Ñ Ð´Ð¾Ñтупу до мережі Tor повніÑÑ‚ÑŽ заборонений: -onion=0</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">Вихідні з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ñ– мережею Tor (-onlynet=onion), але прокÑÑ–-Ñервер Ð´Ð»Ñ Ð´Ð¾Ñтупу до мережі Tor не призначено: не вказано ні -proxy, ні -onion, ані -listenonion</translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">ВиÑвлено нерозпізнаний деÑкриптор. Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ %s
+
+Можливо, гаманець було Ñтворено новішою верÑією.
+Спробуйте найновішу верÑÑ–ÑŽ програми.
+</translation>
+ </message>
+ <message>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished">Ðепідтримуваний категорійний рівень Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ -loglevel=%s. ОчікуєтьÑÑ -loglevel=&lt;category&gt;:&lt;loglevel&gt;. ПрипуÑтимі категорії: %s. ПрипуÑтимі рівні: %s.</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+Ðе вдалоÑÑ Ð¾Ñ‡Ð¸Ñтити помилкове перенеÑеннÑ</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+Ðе вдалоÑÑ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ резервну копію гаманцÑ.</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ— %s заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð¼ÐµÑ€ÐµÐ¶Ñ– %s у розділі [%s].</translation>
</message>
@@ -737,8 +837,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Помилка Ð·Ñ‡Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð°Ñтупного запиÑу з бази даних гаманцÑ</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">Помилка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±Ð°Ð·Ð¸ даних Ñтану ланцюжка</translation>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ транзакцію "тільки переглÑд" до гаманцÑ-длÑ-переглÑду</translation>
+ </message>
+ <message>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ транзакції "тільки переглÑд"</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
@@ -753,6 +857,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Помилка: Контрольна Ñума файлу дампа не збігаєтьÑÑ. ОбчиÑлено %s, очікуєтьÑÑ %s</translation>
</message>
<message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ñтворити новий гаманець-длÑ-переглÑду</translation>
+ </message>
+ <message>
<source>Error: Got key that was not hex: %s</source>
<translation type="unfinished">Помилка: Отримано ключ, що не є hex: %s</translation>
</message>
@@ -773,10 +881,38 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Помилка: Ðемає доÑтупних %s адреÑ.</translation>
</message>
<message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">Помилка: Ðе вÑÑ– транзакції "тільки переглÑд" вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">Помилка; Цей гаманець вже викориÑтовує SQLite</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">Помилка: Цей гаманець вже Ñ” гаманцем на оÑнові деÑкрипторів</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ Ð·Ñ‡Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²ÑÑ–Ñ… запиÑів бази даних</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ð·Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ резервну копію гаманцÑ.</translation>
+ </message>
+ <message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">Помилка: Ðе вдалоÑÑ Ð¿Ñ€Ð¾Ð°Ð½Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ верÑÑ–ÑŽ %u Ñк uint32_t</translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ð·Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ вÑÑ– запиÑи бази даних</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">Помилка: Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ дані "тільки переглÑд" з адреÑної книги</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
<translation type="unfinished">Помилка: Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ нового гаманцÑ</translation>
</message>
@@ -850,13 +986,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation type="unfinished">Вказано некоректну Ñуму Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñƒ -paytxfee: «%s» (повинно бути щонайменше %s)</translation>
+ <translation type="unfinished">Вказано некоректну Ñуму Ð´Ð»Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð° -paytxfee=&lt;amount&gt;: '%s' (повинно бути щонайменше %s)</translation>
</message>
<message>
<source>Invalid netmask specified in -whitelist: '%s'</source>
<translation type="unfinished">Вказано неправильну маÑку підмережі Ð´Ð»Ñ -whitelist: «%s»</translation>
</message>
<message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ñ‚Ð¸ проÑÐ»ÑƒÑ…Ð¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ…Ñ–Ð´Ð½Ð¸Ñ… підключень (listen повернув помилку %s)</translation>
+ </message>
+ <message>
<source>Loading P2P addresses…</source>
<translation type="unfinished">Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ P2P адреÑ…</translation>
</message>
@@ -889,20 +1029,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðемає доÑтупних адреÑ</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Ðе вказано прокÑÑ–-Ñервер. ВикориÑтовуйте -proxy=&lt;ip&gt; або -proxy=&lt;ip:port&gt;.</translation>
- </message>
- <message>
<source>Not enough file descriptors available.</source>
<translation type="unfinished">Бракує доÑтупних деÑкрипторів файлів.</translation>
</message>
<message>
<source>Prune cannot be configured with a negative value.</source>
- <translation type="unfinished">Розмір Ñкороченого ланцюжка блоків не може бути від'ємним.</translation>
- </message>
- <message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">Режим Ñкороченого блокчейна неÑуміÑний з -coinstatsindex.</translation>
+ <translation type="unfinished">Розмір Ñкороченого блокчейна не може бути від'ємним.</translation>
</message>
<message>
<source>Prune mode is incompatible with -txindex.</source>
@@ -1010,7 +1142,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Transaction has too long of a mempool chain</source>
- <translation type="unfinished">Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ñ–Ñ Ð¼Ð°Ñ” занадто довгий ланцюг у пулі</translation>
+ <translation type="unfinished">Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ñ–Ñ Ð¼Ð°Ñ” занадто довгий ланцюг у пулі транзакцій</translation>
</message>
<message>
<source>Transaction must have at least one recipient</source>
@@ -1025,24 +1157,32 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ñ–Ñ Ð·Ð°Ð½Ð°Ð´Ñ‚Ð¾ велика</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð²Ð¸Ð´Ñ–Ð»Ð¸Ñ‚Ð¸ пам'ÑÑ‚ÑŒ Ð´Ð»Ñ -maxsigcachesize: '%s' МіБ</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
- <translation type="unfinished">Ðеможливо прив'ÑзатиÑÑ Ð´Ð¾ %s на цьому комп'ютері (bind повернув помилку: %s)</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð¿Ñ€Ð¸Ð²'ÑзатиÑÑ Ð´Ð¾ %s на цьому комп'ютері (bind повернув помилку: %s)</translation>
</message>
<message>
<source>Unable to bind to %s on this computer. %s is probably already running.</source>
- <translation type="unfinished">Ðеможливо прив'Ñзати %s на цьому комп'ютері. %s, ймовірно, вже працює.</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð¿Ñ€Ð¸Ð²'Ñзати %s на цьому комп'ютері. %s, ймовірно, вже працює.</translation>
</message>
<message>
<source>Unable to create the PID file '%s': %s</source>
- <translation type="unfinished">Ðеможливо Ñтворити PID файл '%s' :%s</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ñтворити PID файл '%s' :%s</translation>
+ </message>
+ <message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ UTXO Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ входу</translation>
</message>
<message>
<source>Unable to generate initial keys</source>
- <translation type="unfinished">Ðе вдаєтьÑÑ Ñтворити початкові ключі</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ñтворити початкові ключі</translation>
</message>
<message>
<source>Unable to generate keys</source>
- <translation type="unfinished">Ðе вдаєтьÑÑ Ñтворити ключі</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ñтворити ключі</translation>
</message>
<message>
<source>Unable to open %s for writing</source>
@@ -1054,7 +1194,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unable to start HTTP server. See debug log for details.</source>
- <translation type="unfinished">Ðеможливо запуÑтити HTTP-Ñервер. Детальніший Ð¾Ð¿Ð¸Ñ Ð½Ð°Ð²ÐµÐ´ÐµÐ½Ð¾ в журналі зневадженнÑ.</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити HTTP-Ñервер. Детальніший Ð¾Ð¿Ð¸Ñ Ð½Ð°Ð²ÐµÐ´ÐµÐ½Ð¾ в журналі зневадженнÑ.</translation>
+ </message>
+ <message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð²Ð¸Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ гаманець перед перенеÑеннÑм</translation>
</message>
<message>
<source>Unknown -blockfilterindex value %s.</source>
@@ -1077,12 +1221,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ðктивовані невідомі нові правила (versionbit %i)</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">Ðепідтримувана ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ %s=%s.</translation>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">Ðепідтримуваний глобальний рівень Ð¶ÑƒÑ€Ð½Ð°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ -loglevel=%s. ПрипуÑтимі значеннÑ: %s.</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±Ð°Ð·Ð¸ даних UTXO</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">Ðепідтримувана ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ñ–Ñ Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñƒ %s=%s.</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -1194,7 +1338,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Encrypt Wallet…</source>
- <translation type="unfinished">За&amp;шифрувати гаманець…</translation>
+ <translation type="unfinished">&amp;Шифрувати Гаманець...</translation>
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
@@ -1206,23 +1350,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Change Passphrase…</source>
- <translation type="unfinished">Змінити парол&amp;ь…</translation>
+ <translation type="unfinished">Змінити парол&amp;ь...</translation>
</message>
<message>
<source>Sign &amp;message…</source>
- <translation type="unfinished">&amp;ПідпиÑати повідомленнÑ…</translation>
+ <translation type="unfinished">&amp;ПідпиÑати повідомленнÑ...</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Підтвердіть, що ви Ñ” влаÑником Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñавши його вашою Bitcoin-адреÑою</translation>
+ <translation type="unfinished">Підтвердіть, що Ви Ñ” влаÑником повідомленнÑ, підпиÑавши його Вашою біткоїн-адреÑою</translation>
</message>
<message>
<source>&amp;Verify message…</source>
- <translation type="unfinished">П&amp;еревірити повідомленнÑ…</translation>
+ <translation type="unfinished">П&amp;еревірити повідомленнÑ...</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation type="unfinished">Перевірте Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ð¿ÐµÐ²Ð½ÐµÐ½Ð¾ÑÑ‚Ñ–, що воно підпиÑано вказаною Bitcoin-адреÑою</translation>
+ <translation type="unfinished">Перевірте Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²Ð¿ÐµÐ²Ð½ÐµÐ½Ð¾ÑÑ‚Ñ–, що воно підпиÑано вказаною біткоїн-адреÑою</translation>
</message>
<message>
<source>&amp;Load PSBT from file…</source>
@@ -1234,15 +1378,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Close Wallet…</source>
- <translation type="unfinished">Закрити Гаманець…</translation>
+ <translation type="unfinished">Закрити гаманець…</translation>
</message>
<message>
<source>Create Wallet…</source>
- <translation type="unfinished">Створити Гаманець…</translation>
+ <translation type="unfinished">Створити гаманець…</translation>
</message>
<message>
<source>Close All Wallets…</source>
- <translation type="unfinished">Закрити Ð’ÑÑ– Гаманці…</translation>
+ <translation type="unfinished">Закрити вÑÑ– гаманці…</translation>
</message>
<message>
<source>&amp;File</source>
@@ -1341,10 +1485,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Синхронізовано</translation>
</message>
<message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">Завантажити чаÑтково підпиÑану біткоїн-транзакцію (PSBT)</translation>
+ </message>
+ <message>
<source>Load PSBT from &amp;clipboard…</source>
<translation type="unfinished">Завантажити PSBT-транзакцію з &amp;буфера обміну…</translation>
</message>
<message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation type="unfinished">Завантажити чаÑтково підпиÑану біткоїн-транзакцію (PSBT) з буфера обміну</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation type="unfinished">Вікно вузла</translation>
</message>
@@ -1377,6 +1529,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Закрити гаманець</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Відновити гаманець…</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Відновити гаманець з файлу резервної копії</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">Закрити вÑÑ– гаманці</translation>
</message>
@@ -1386,7 +1548,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Mask values</source>
- <translation type="unfinished">&amp;Приховати значеннÑ</translation>
+ <translation type="unfinished">При&amp;ховати значеннÑ</translation>
</message>
<message>
<source>Mask the values in the Overview tab</source>
@@ -1401,6 +1563,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Гаманців немає</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">Файл гаманцÑ</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Завантажити резервну копію гаманцÑ</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Відновити гаманець</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">Ðазва гаманцÑ</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">&amp;Вікно</translation>
</message>
@@ -1428,9 +1610,9 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform>%n активне з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею Bitcoin</numerusform>
- <numerusform>%n активних з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею Bitcoin</numerusform>
- <numerusform>%n активних з'єднань з мережею Bitcoin</numerusform>
+ <numerusform>%n активне з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею Біткоїн.</numerusform>
+ <numerusform>%n активних з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею Біткоїн.</numerusform>
+ <numerusform>%n активних з'єднань з мережею Біткоїн.</numerusform>
</translation>
</message>
<message>
@@ -1454,6 +1636,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Увімкнути мережеву активніÑÑ‚ÑŒ</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">Триває Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÑ–Ð² (%1%)…</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">Помилка: %1</translation>
</message>
@@ -1716,6 +1902,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">Ðеможливо показати зовнішні підпиÑувачі</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Знайдено забагато зовнішних підпиÑувачів</translation>
+ </message>
</context>
<context>
<name>LoadWalletsActivity</name>
@@ -1756,6 +1946,34 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Відновити гаманець</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ &lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Помилка Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1786,7 +2004,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Wallet Name</source>
- <translation type="unfinished">Ðазва ГаманцÑ</translation>
+ <translation type="unfinished">Ðазва гаманцÑ</translation>
</message>
<message>
<source>Wallet</source>
@@ -1794,7 +2012,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
- <translation type="unfinished">Зашифруйте гаманець. Гаманець буде зашифрований за допомогою Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ð° ваш вибір.</translation>
+ <translation type="unfinished">Зашифрувати гаманець. Гаманець буде зашифрований за допомогою обраного вами паролÑ.</translation>
</message>
<message>
<source>Encrypt Wallet</source>
@@ -1806,7 +2024,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<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">Вимкнути приватні ключі Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ гаманцÑ. Гаманці з вимкнутими приватними ключами не матимуть приватних ключів Ñ– не можуть мати набір HD або імпортовані приватні ключі. Це ідеально підходить лише Ð´Ð»Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸-оглÑд гаманців.</translation>
+ <translation type="unfinished">Вимкнути приватні ключі Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ гаманцÑ. Гаманці з вимкнутими приватними ключами не матимуть приватних ключів Ñ– не можуть мати набір HD-генератор або імпортовані приватні ключі. Це ідеально підходить Ð´Ð»Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ–Ð²-длÑ-переглÑду.</translation>
</message>
<message>
<source>Disable Private Keys</source>
@@ -1814,7 +2032,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>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>
- <translation type="unfinished">Зробіть порожній гаманець. Порожні гаманці Ñпочатку не мають приватних ключів або Ñценаріїв. Пізніше можна імпортувати приватні ключі та адреÑи або вÑтановити HD-наÑіннÑ.</translation>
+ <translation type="unfinished">Створити пуÑтий гаманець. ПуÑÑ‚Ñ– гаманці Ñпочатку не мають приватних ключів або Ñкриптів. Пізніше можна імпортувати приватні ключі та адреÑи або вÑтановити HD-генератор.</translation>
</message>
<message>
<source>Make Blank Wallet</source>
@@ -1822,11 +2040,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Use descriptors for scriptPubKey management</source>
- <translation type="unfinished">ВикориÑтовуйте деÑкриптори Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ scriptPubKey</translation>
+ <translation type="unfinished">ВикориÑтовувати деÑкриптори Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ scriptPubKey</translation>
</message>
<message>
<source>Descriptor Wallet</source>
- <translation type="unfinished">Гаманець на базі деÑкрипторів</translation>
+ <translation type="unfinished">Гаманець на оÑнові деÑкрипторів</translation>
</message>
<message>
<source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
@@ -1842,12 +2060,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Compiled without sqlite support (required for descriptor wallets)</source>
- <translation type="unfinished">Зкомпільовано без підтримки sqlite (потрібно Ð´Ð»Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ–Ð² деÑкрипторів)</translation>
+ <translation type="unfinished">Скомпільовано без підтримки sqlite (потрібно Ð´Ð»Ñ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ–Ð² на оÑнові деÑкрипторів)</translation>
</message>
<message>
<source>Compiled without external signing support (required for external signing)</source>
<extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Скомпільовано без підтримки зовнішнього підпиÑуваннÑ</translation>
+ <translation type="unfinished">Скомпільовано без підтримки зовнішнього підпиÑÑƒÐ²Ð°Ð½Ð½Ñ (потрібно Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ підпиÑуваннÑ)</translation>
</message>
</context>
<context>
@@ -1886,7 +2104,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation type="unfinished">Введена адреÑа "%1" не Ñ” дійÑною Bitcoin адреÑою.</translation>
+ <translation type="unfinished">Введена адреÑа "%1" не Ñ” дійÑною біткоїн-адреÑою.</translation>
</message>
<message>
<source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
@@ -1930,17 +2148,29 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
- <message>
- <source>%1 GB of space available</source>
- <translation type="unfinished">ДоÑтупно %1 ГБ</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>ДоÑтупний проÑÑ‚Ñ–Ñ€: %n ГБ</numerusform>
+ <numerusform>ДоÑтупний проÑÑ‚Ñ–Ñ€: %n ГБ</numerusform>
+ <numerusform>ДоÑтупний проÑÑ‚Ñ–Ñ€: %n ГБ</numerusform>
+ </translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(з %1 ГБ, що потрібно)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(в той чаÑ, Ñк необхідно %n ГБ)</numerusform>
+ <numerusform>(в той чаÑ, Ñк необхідно %n ГБ)</numerusform>
+ <numerusform>(в той чаÑ, Ñк необхідно %n ГБ)</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(%1 ГБ, необхідних Ð´Ð»Ñ Ð¿Ð¾Ð²Ð½Ð¾Ð³Ð¾ блокчейну)</translation>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(%n ГБ необхідно Ð´Ð»Ñ Ð¿Ð¾Ð²Ð½Ð¾Ð³Ð¾ блокчейну)</numerusform>
+ <numerusform>(%n ГБ необхідно Ð´Ð»Ñ Ð¿Ð¾Ð²Ð½Ð¾Ð³Ð¾ блокчейну)</numerusform>
+ <numerusform>(%n ГБ необхідно Ð´Ð»Ñ Ð¿Ð¾Ð²Ð½Ð¾Ð³Ð¾ блокчейну)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1988,10 +2218,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ОÑкільки це перший запуÑк програми, ви можете обрати, де %1 буде зберігати дані.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">ПіÑÐ»Ñ Ð½Ð°Ñ‚Ð¸ÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ «OK» %1 почне завантажувати та оброблÑти повний ланцюжок блоків %4 (%2 ГБ), починаючи з найбільш ранніх транзакцій у %3, коли було запущено %4.</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">Скоротити міÑце під блоки до</translation>
</message>
@@ -2008,8 +2234,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ð¦Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÐ¾Ð²Ð° ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ñ” дуже вимогливою, Ñ– може виÑвити проблеми з апаратним забезпеченнÑм комп'ютера, Ñкі раніше не були непоміченими. Кожен раз, коли ви запуÑкаєте %1, він буде продовжувати Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð°Ð¼, де він зупинивÑÑ.</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">ПіÑÐ»Ñ Ð½Ð°Ñ‚Ð¸ÑÐºÐ°Ð½Ð½Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ «OK» %1 почне завантажувати та оброблÑти повний блокчейн %4 (%2 ГБ), починаючи з найбільш ранніх транзакцій у %3, коли було запущено %4.</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation type="unfinished">Якщо ви вирішили обмежити Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð»Ð°Ð½Ñ†ÑŽÐ¶ÐºÐ° блоків (відÑіканнÑ), Ñ–Ñторичні дані повинні бути завантажені та оброблені, але потім можуть бути видалені, щоб зберегти потрібний проÑÑ‚Ñ–Ñ€ диÑка.</translation>
+ <translation type="unfinished">Якщо ви вирішили обмежити обÑÑг Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð±Ð»Ð¾ÐºÑ‡ÐµÐ¹Ð½Ð°, Ñ–Ñторичні дані повинні бути завантажені та оброблені, але потім можуть бути видалені, щоб зберегти потрібний проÑÑ‚Ñ–Ñ€ диÑка.</translation>
</message>
<message>
<source>Use the default data directory</source>
@@ -2054,7 +2284,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation type="unfinished">Ðещодавні транзакції ще не відображаютьÑÑ, тому Ð±Ð°Ð»Ð°Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ Ð¼Ð¾Ð¶Ðµ бути неточним. Ð¦Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ вірною піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ваш гаманець завершить Ñинхронізацію з мережею Біткоїн, враховуйте показники нижче.</translation>
+ <translation type="unfinished">Ðещодавні транзакції ще не відображаютьÑÑ, тому Ð±Ð°Ð»Ð°Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð³Ð°Ð¼Ð°Ð½Ñ†Ñ Ð¼Ð¾Ð¶Ðµ бути неточним. Ð¦Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ вірною піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ваш гаманець завершить Ñинхронізацію з мережею Біткоїн (дивітьÑÑ Ð½Ð¸Ð¶Ñ‡Ðµ).</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
@@ -2078,11 +2308,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Progress</source>
- <translation type="unfinished">ПрогреÑ</translation>
+ <translation type="unfinished">Перебіг Ñинхронізації</translation>
</message>
<message>
<source>Progress increase per hour</source>
- <translation type="unfinished">ÐŸÑ€Ð¾Ð³Ñ€ÐµÑ Ð·Ð° годину</translation>
+ <translation type="unfinished">ÐŸÑ€Ð¾Ð³Ñ€ÐµÑ Ñинхронізації за годину</translation>
</message>
<message>
<source>Estimated time left until synced</source>
@@ -2098,7 +2328,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
- <translation type="unfinished">Ðевідомо. Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÑ–Ð² (%1, %2%)…</translation>
+ <translation type="unfinished">Ðевідомо. Триває ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÑ–Ð² (%1, %2%)…</translation>
+ </message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Ðевідомо. Триває Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÑ–Ð² (%1, %2%)…</translation>
</message>
</context>
<context>
@@ -2129,7 +2363,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Start %1 on system login</source>
- <translation type="unfinished">&amp;ЗапуÑкати %1 при вході в ÑиÑтему</translation>
+ <translation type="unfinished">ЗапуÑкати %1 при в&amp;ході в ÑиÑтему</translation>
</message>
<message>
<source>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>
@@ -2137,7 +2371,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Size of &amp;database cache</source>
- <translation type="unfinished">Розмір &amp;кешу бази даних</translation>
+ <translation type="unfinished">Розмір ке&amp;шу бази даних</translation>
</message>
<message>
<source>Number of script &amp;verification threads</source>
@@ -2156,6 +2390,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Згортати заміÑÑ‚ÑŒ закриттÑ. Якщо Ñ†Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°, програма закриєтьÑÑ Ð»Ð¸ÑˆÐµ піÑÐ»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ відповідного пункту в меню.</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Параметри, Ñкі задані в цьому вікні, змінені командним Ñ€Ñдком:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">Відкрийте %1 файл конфігурації з робочого каталогу.</translation>
</message>
@@ -2185,7 +2423,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation type="unfinished">ÐŸÐ¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— опції вимагає Ð¿ÐµÑ€ÐµÐ·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²ÑŒÐ¾Ð³Ð¾ ланцюжка блоків.</translation>
+ <translation type="unfinished">ÐŸÐ¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ параметра вимагає Ð¿ÐµÑ€ÐµÐ·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²ÑŒÐ¾Ð³Ð¾ блокчейна.</translation>
</message>
<message>
<source>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>
@@ -2213,7 +2451,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>Enable R&amp;PC server</source>
<extracomment>An Options window setting to enable the RPC server.</extracomment>
- <translation type="unfinished">Увімкнути RPC &amp;Ñервер</translation>
+ <translation type="unfinished">Увімкнути RPC Ñе&amp;рвер</translation>
</message>
<message>
<source>W&amp;allet</source>
@@ -2227,7 +2465,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>Subtract &amp;fee from amount by default</source>
<extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
- <translation type="unfinished">За замовчуваннÑм віднімати &amp;коміÑÑ–ÑŽ від Ñуми відправленнÑ.</translation>
+ <translation type="unfinished">За замовчуваннÑм віднімати &amp;коміÑÑ–ÑŽ від Ñуми відправленнÑ</translation>
</message>
<message>
<source>Expert</source>
@@ -2235,7 +2473,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Enable coin &amp;control features</source>
- <translation type="unfinished">Ввімкнути &amp;ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ…Ð¾Ð´Ð°Ð¼Ð¸</translation>
+ <translation type="unfinished">Ввімкнути ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²&amp;ходами</translation>
</message>
<message>
<source>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>
@@ -2243,12 +2481,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
- <translation type="unfinished">&amp;Витрачати непідтверджену решту</translation>
+ <translation type="unfinished">Витрачати непідтверджену &amp;решту</translation>
</message>
<message>
<source>Enable &amp;PSBT controls</source>
<extracomment>An options window setting to enable PSBT controls.</extracomment>
- <translation type="unfinished">Увімкнути елементи ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ &amp;PSBT</translation>
+ <translation type="unfinished">Увімкнути функції &amp;чаÑтково підпиÑаних біткоїн-транзакцій (PSBT)</translation>
</message>
<message>
<source>Whether to show PSBT controls.</source>
@@ -2261,7 +2499,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;External signer script path</source>
- <translation type="unfinished">ШлÑÑ… до Ñкрипту &amp;зовнішнього підпиÑувача</translation>
+ <translation type="unfinished">&amp;ШлÑÑ… до Ñкрипту зовнішнього підпиÑувача</translation>
</message>
<message>
<source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
@@ -2293,7 +2531,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation type="unfinished">ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ мережі Bitcoin через SOCKS5 прокÑÑ–.</translation>
+ <translation type="unfinished">ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ мережі Біткоїн через SOCKS5 прокÑÑ–.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
@@ -2325,7 +2563,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Show tray icon</source>
- <translation type="unfinished">&amp;Показувати піктограму у ÑиÑтемному треї</translation>
+ <translation type="unfinished">Показувати &amp;піктограму у ÑиÑтемному треї</translation>
</message>
<message>
<source>Show only a tray icon after minimizing the window.</source>
@@ -2333,11 +2571,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation type="unfinished">Мінімізувати &amp;у трей</translation>
+ <translation type="unfinished">Мінімізувати у &amp;трей</translation>
</message>
<message>
<source>M&amp;inimize on close</source>
- <translation type="unfinished">Згортати заміÑÑ‚ÑŒ закритт&amp;Ñ</translation>
+ <translation type="unfinished">Зго&amp;ртати заміÑÑ‚ÑŒ закриттÑ</translation>
</message>
<message>
<source>&amp;Display</source>
@@ -2392,17 +2630,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">найбільш подібний "%1"</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Параметри, Ñкі задані в цьому вікні, змінені командним Ñ€Ñдком або у файлі конфігурації:</translation>
- </message>
- <message>
<source>&amp;Cancel</source>
<translation type="unfinished">&amp;СкаÑувати</translation>
</message>
<message>
<source>Compiled without external signing support (required for external signing)</source>
<extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
- <translation type="unfinished">Скомпільовано без підтримки зовнішнього підпиÑуваннÑ</translation>
+ <translation type="unfinished">Скомпільовано без підтримки зовнішнього підпиÑÑƒÐ²Ð°Ð½Ð½Ñ (потрібно Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ підпиÑуваннÑ)</translation>
</message>
<message>
<source>default</source>
@@ -2414,14 +2648,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ–Ð²</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Ð”Ð»Ñ Ð·Ð°ÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ð½ необхідно перезапуÑтити клієнта.</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished"> Поточні параметри будуть збережені в "%1".</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">Клієнт буде закрито. Продовжити?</translation>
</message>
<message>
@@ -2432,7 +2674,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>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>
<extracomment>Explanatory text about the priority order of instructions considered by client. The order from high to low being: command-line, configuration file, GUI settings.</extracomment>
- <translation type="unfinished">Файл конфігурації викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²ÐºÐ°Ð·ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ñ… параметрів кориÑтувача, що перекривають наÑтройки графічного інтерфейÑу кориÑтувача. Крім того, будь-Ñкі параметри командного Ñ€Ñдка замінÑÑ‚ÑŒ цей конфігураційний файл.</translation>
+ <translation type="unfinished">Файл конфігурації викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²ÐºÐ°Ð·ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ñ… параметрів, що перевизначають параметри графічного інтерфейÑу. Крім того, будь-Ñкі параметри командного Ñ€Ñдка перевизначать цей конфігураційний файл.</translation>
</message>
<message>
<source>Continue</source>
@@ -2460,6 +2702,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ параметр "%1", %2.</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2471,7 +2720,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Watch-only:</source>
- <translation type="unfinished">Тільки ÑпоÑтереженнÑ:</translation>
+ <translation type="unfinished">Тільки переглÑд:</translation>
</message>
<message>
<source>Available:</source>
@@ -2511,7 +2760,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation type="unfinished">Ваш поточний Ð±Ð°Ð»Ð°Ð½Ñ Ð² адреÑах Ð´Ð»Ñ ÑпоÑтереженнÑ</translation>
+ <translation type="unfinished">Ваш поточний Ð±Ð°Ð»Ð°Ð½Ñ Ð² адреÑах "тільки переглÑд"</translation>
</message>
<message>
<source>Spendable:</source>
@@ -2523,15 +2772,15 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
- <translation type="unfinished">Ðепідтверджені транзакції на адреÑи Ð´Ð»Ñ ÑпоÑтереженнÑ</translation>
+ <translation type="unfinished">Ðепідтверджені транзакції на адреÑи "тільки переглÑд"</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation type="unfinished">Ð‘Ð°Ð»Ð°Ð½Ñ Ð²Ð¸Ð´Ð¾Ð±ÑƒÑ‚Ð¸Ñ… монет, що не доÑÑгли завершеноÑÑ‚Ñ–, на адреÑах Ð´Ð»Ñ ÑпоÑтереженнÑ</translation>
+ <translation type="unfinished">Ð‘Ð°Ð»Ð°Ð½Ñ Ð²Ð¸Ð´Ð¾Ð±ÑƒÑ‚Ð¸Ñ… монет, що не доÑÑгли завершеноÑÑ‚Ñ–, на адреÑах "тільки переглÑд"</translation>
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation type="unfinished">Поточний Ñукупний Ð±Ð°Ð»Ð°Ð½Ñ Ð² адреÑах Ð´Ð»Ñ ÑпоÑтереженнÑ</translation>
+ <translation type="unfinished">Поточний Ñукупний Ð±Ð°Ð»Ð°Ð½Ñ Ð² адреÑах "тільки переглÑд"</translation>
</message>
<message>
<source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
@@ -2611,7 +2860,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message>
<source>Partially Signed Transaction (Binary)</source>
<extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
- <translation type="unfinished">ЧаÑтково підпиÑана Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ñ–Ñ (Binary)</translation>
+ <translation type="unfinished">ЧаÑтково підпиÑана біткоїн-Ñ‚Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ñ–Ñ (бінарний файл)</translation>
</message>
<message>
<source>PSBT saved to disk.</source>
@@ -2623,7 +2872,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Unable to calculate transaction fee or total transaction amount.</source>
- <translation type="unfinished">Ðеможливо розрахувати коміÑÑ–ÑŽ за транзакцію або загальну Ñуму транзакції.</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ñ€Ð¾Ð·Ñ€Ð°Ñ…ÑƒÐ²Ð°Ñ‚Ð¸ коміÑÑ–ÑŽ за транзакцію або загальну Ñуму транзакції.</translation>
</message>
<message>
<source>Pays transaction fee: </source>
@@ -2723,6 +2972,11 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">УчаÑник</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">ТриваліÑÑ‚ÑŒ</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">ÐапрÑмок</translation>
@@ -2923,29 +3177,32 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Whether we relay addresses to this peer.</source>
- <extracomment>Tooltip text for the Address Relay field in the peer details area.</extracomment>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">Чи ретранÑлювати адреÑи цьому учаÑнику.</translation>
</message>
<message>
<source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
<translation type="unfinished">РетранÑÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð°Ð´Ñ€ÐµÑ</translation>
</message>
<message>
- <source>Total number of addresses processed, excluding those dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Processed field in the peer details area.</extracomment>
- <translation type="unfinished">Загальна кількіÑÑ‚ÑŒ оброблених Ð°Ð´Ñ€ÐµÑ Ð·Ð° винÑтком пропущених через Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти.</translation>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Загальна кількіÑÑ‚ÑŒ отриманих від цього учаÑника адреÑ, що були оброблені (за винÑтком адреÑ, пропущених через Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‚ÐµÐ¼Ð¿Ñƒ).</translation>
</message>
<message>
- <source>Addresses Processed</source>
- <translation type="unfinished">ÐÐ´Ñ€ÐµÑ Ð¾Ð±Ñ€Ð¾Ð±Ð»ÐµÐ½Ð¾</translation>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Загальна кількіÑÑ‚ÑŒ отриманих від цього учаÑника адреÑ, що були пропущені (не оброблені) через Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‚ÐµÐ¼Ð¿Ñƒ.</translation>
</message>
<message>
- <source>Total number of addresses dropped due to rate-limiting.</source>
- <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area.</extracomment>
- <translation type="unfinished">Загальна кількіÑÑ‚ÑŒ адреÑ, пропущених через Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти.</translation>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">ÐÐ´Ñ€ÐµÑ Ð¾Ð±Ñ€Ð¾Ð±Ð»ÐµÐ½Ð¾</translation>
</message>
<message>
<source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
<translation type="unfinished">ÐÐ´Ñ€ÐµÑ Ð¿Ñ€Ð¾Ð¿ÑƒÑ‰ÐµÐ½Ð¾</translation>
</message>
<message>
@@ -2954,7 +3211,7 @@ If you are receiving this error you should request the merchant provide a BIP21
</message>
<message>
<source>Node window</source>
- <translation type="unfinished">Вікно вузлів</translation>
+ <translation type="unfinished">Вікно вузла</translation>
</message>
<message>
<source>Current block height</source>
@@ -3252,7 +3509,7 @@ For more information on using this console, type %6.
</message>
<message>
<source>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>
- <translation type="unfinished">Ðеобов'Ñзкове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð° додаток до запиту платежу, котре буде показане під Ñ‡Ð°Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ. Примітка: Це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ðµ буде відправлено з платежем через мережу Bitcoin.</translation>
+ <translation type="unfinished">Ðеобов'Ñзкове Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð° додаток до запиту платежу, Ñке буде показане під Ñ‡Ð°Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ. Примітка: це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ðµ буде відправлено з платежем через мережу Біткоїн.</translation>
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
@@ -3581,7 +3838,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Copy amount</source>
- <translation type="unfinished">Копіювати Ñуму</translation>
+ <translation type="unfinished">Скопіювати Ñуму</translation>
</message>
<message>
<source>Copy fee</source>
@@ -3722,7 +3979,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Watch-only balance:</source>
- <translation type="unfinished">Ð‘Ð°Ð»Ð°Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ ÑпоÑтереженнÑ:</translation>
+ <translation type="unfinished">Ð‘Ð°Ð»Ð°Ð½Ñ "тільки переглÑд":</translation>
</message>
<message>
<source>The recipient address is not valid. Please recheck.</source>
@@ -3752,10 +4009,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">КоміÑÑ–Ñ Ð±Ñ–Ð»ÑŒÑˆÐ°, ніж %1, вважаєтьÑÑ Ð°Ð±Ñурдно виÑокою.</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Запит платежу проÑтрочено.</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -3805,7 +4058,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
- <translation type="unfinished">ÐдреÑа Bitcoin Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð»Ð°Ñ‚ÐµÐ¶Ñƒ</translation>
+ <translation type="unfinished">Біткоїн-адреÑа Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð»Ð°Ñ‚ÐµÐ¶Ñƒ</translation>
</message>
<message>
<source>Paste address from clipboard</source>
@@ -3836,28 +4089,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">ПовідомленнÑ:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Цей запит платежу не є автентифікованим.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Цей запит платежу є автентифікованим.</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">Введіть мітку Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— адреÑи Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ—Ñ— в ÑпиÑок викориÑтаних адреÑ</translation>
</message>
<message>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
- <translation type="unfinished">ПовідомленнÑ, що було додане до bitcoin:URI та буде збережено разом з транзакцією Ð´Ð»Ñ Ð´Ð¾Ð²Ñ–Ð´ÐºÐ¸. Примітка: Це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ðµ буде відправлено в мережу Bitcoin.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Отримувач:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Ðотатка:</translation>
+ <translation type="unfinished">ПовідомленнÑ, що було додане до bitcoin:URI та буде збережено разом з транзакцією Ð´Ð»Ñ Ð´Ð¾Ð²Ñ–Ð´ÐºÐ¸. Примітка: це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ðµ буде відправлено в мережу Біткоїн.</translation>
</message>
</context>
<context>
@@ -4036,30 +4273,32 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">конфліктує з транзакцією із %1 підтвердженнÑми</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/не підтверджено, %1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">у пулі транзакцій</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/не підтверджено, в пулі транзакцій</translation>
</message>
<message>
- <source>not in memory pool</source>
- <translation type="unfinished">не в пулі транзакцій</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/не підтверджено, не в пулі транзакцій</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">відкинуто</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/не підтверджено</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 підтверджень</translation>
</message>
<message>
@@ -4096,7 +4335,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>watch-only</source>
- <translation type="unfinished">тільки ÑпоÑтереженнÑ</translation>
+ <translation type="unfinished">тільки переглÑд</translation>
</message>
<message>
<source>label</source>
@@ -4172,7 +4411,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
- <translation type="unfinished">Згенеровані монети Ñтануть доÑтупні Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ %1 підтверджень. Коли ви згенерували цей блок, його було відправлено в мережу Ð´Ð»Ñ Ð²Ð½ÐµÑÐµÐ½Ð½Ñ Ð´Ð¾ ланцюжку блоків. Якщо блок не буде додано до ланцюжку блоків, його ÑÑ‚Ð°Ñ‚ÑƒÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚ÑŒÑÑ Ð½Ð° «не підтверджено», Ñ– згенеровані монети неможливо буде витратити. Таке чаÑом траплÑєтьÑÑ, Ñкщо хтоÑÑŒ згенерував інший блок на декілька Ñекунд раніше.</translation>
+ <translation type="unfinished">Згенеровані монети Ñтануть доÑтупні Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ %1 підтверджень. Коли ви згенерували цей блок, його було відправлено в мережу Ð´Ð»Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ блокчейна. Якщо блок не буде додано до блокчейна, його ÑÑ‚Ð°Ñ‚ÑƒÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚ÑŒÑÑ Ð½Ð° «не підтверджено», Ñ– згенеровані монети неможливо буде витратити. Таке чаÑом траплÑєтьÑÑ, Ñкщо хтоÑÑŒ згенерував інший блок на декілька Ñекунд раніше.</translation>
</message>
<message>
<source>Debug information</source>
@@ -4274,7 +4513,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>watch-only</source>
- <translation type="unfinished">тільки ÑпоÑтереженнÑ</translation>
+ <translation type="unfinished">тільки переглÑд</translation>
</message>
<message>
<source>(n/a)</source>
@@ -4298,7 +4537,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation type="unfinished">Чи було залучено адреÑу Ð´Ð»Ñ ÑпоÑÑ‚ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð² цій транзакції.</translation>
+ <translation type="unfinished">Чи було залучено адреÑу "тільки переглÑд" в цій транзакції.</translation>
</message>
<message>
<source>User-defined intent/purpose of the transaction.</source>
@@ -4427,7 +4666,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Watch-only</source>
- <translation type="unfinished">Тільки ÑпоÑтереженнÑ:</translation>
+ <translation type="unfinished">Тільки переглÑд</translation>
</message>
<message>
<source>Date</source>
@@ -4494,7 +4733,7 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<source>Unable to decode PSBT from clipboard (invalid base64)</source>
- <translation type="unfinished">Ðе вдаєтьÑÑ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ñ‚Ð¸ PSBT-транзакцію з буфера обміну (неприпуÑтимий base64)</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ñ‚Ð¸ PSBT-транзакцію з буфера обміну (неприпуÑтимий base64)</translation>
</message>
<message>
<source>Load Transaction Data</source>
@@ -4510,7 +4749,7 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<source>Unable to decode PSBT</source>
- <translation type="unfinished">Ðе вдаєтьÑÑ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ñ‚Ð¸ PSBT-транзакцію</translation>
+ <translation type="unfinished">Ðе вдалоÑÑ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ñ‚Ð¸ PSBT-транзакцію</translation>
</message>
</context>
<context>
@@ -4585,7 +4824,7 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation type="unfinished">ЕкÑпортувати дані з поточної вкладки в файл</translation>
+ <translation type="unfinished">ЕкÑпортувати дані з поточної вкладки у файл</translation>
</message>
<message>
<source>Backup Wallet</source>
diff --git a/src/qt/locale/bitcoin_ur.ts b/src/qt/locale/bitcoin_ur.ts
index 54e090a69f..0c23d8b6ec 100644
--- a/src/qt/locale/bitcoin_ur.ts
+++ b/src/qt/locale/bitcoin_ur.ts
@@ -285,9 +285,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">%1ابھی تک سلامتی سے باÛر Ù†Ûیں نکلا…</translation>
</message>
<message>
+ <source>unknown</source>
+ <translation type="unfinished">نامعلوم</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation type="unfinished">رقم</translation>
</message>
+ <message>
+ <source>Unroutable</source>
+ <translation type="unfinished">ناقابل استعمال</translation>
+ </message>
+ <message>
+ <source>Internal</source>
+ <translation type="unfinished">اندرونی</translation>
+ </message>
+ <message>
+ <source>Address Fetch</source>
+ <extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
+ <translation type="unfinished">Ù¾ØªÛ Ø¨Ø§Ø²ÛŒØ§Ùت کریں۔</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation type="unfinished">ملی سیکنڈز %1</translation>
+ </message>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
@@ -465,6 +486,66 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Create Wallet…</source>
<translation type="unfinished">والیٹ بنائیں…</translation>
</message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">تمام والیٹس بند کردیں</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation type="unfinished">اور Ùائل</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation type="unfinished">اور ترتیبات</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation type="unfinished">اور مدد</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation type="unfinished">ٹیبز ٹول بار</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished"> '%1%' Ûیڈرز Ú©ÛŒ مطابقت پذیری</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">نیٹ ورک Ú©Û’ ساتھ ÛÙ… Ø¢ÛÙ†Ú¯ ÛÙˆ کر</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">ڈسک پر بلاکس کو ترتیب دینا</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">ڈسک پر بلاکس کو پراسیس کرنا</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">ڈسک پر بلاکس Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û ØªØ±ØªÛŒØ¨ دینا</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">ساتھیوں سے منسلک کرنے</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation type="unfinished">ادائیگی کی درخواست کریں: ( کوئیک رسپانس ( کیو۔آر ) کوڈ اور بٹ کوائن ( یونیورسل ادائیگیوں کا نظام) کے ذریعے سے</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation type="unfinished">استعمال Ø´Ø¯Û Ø¨Ú¾ÛŒØ¬Ù†Û’ والے پتے اور لیبلز Ú©ÛŒ ÙÛرست دکھائیں۔</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation type="unfinished">استعمال Ø´Ø¯Û ÙˆØµÙˆÙ„ کرنے والے پتوں اور لیبلز Ú©ÛŒ ÙÛرست دکھائیں۔</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation type="unfinished">اور کمانڈ لائن اختیارات</translation>
+ </message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
@@ -473,9 +554,122 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
+ <source>%1 behind</source>
+ <translation type="unfinished">'%1'پیچھے</translation>
+ </message>
+ <message>
+ <source>Catching up…</source>
+ <translation type="unfinished">پکڑنا</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation type="unfinished">آخری موصول Ø´Ø¯Û 1 '%1' Ù¾ÛÙ„Û’ تیار کیا گیا تھا۔</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation type="unfinished">اس Ú©Û’ بعد Ú©ÛŒ لین دین ابھی نظر Ù†Ûیں آئے گی۔</translation>
+ </message>
+ <message>
<source>Error</source>
<translation type="unfinished">نقص</translation>
</message>
+ <message>
+ <source>Warning</source>
+ <translation type="unfinished">انتباÛ</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation type="unfinished">معلومات</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation type="unfinished">سب سے نیا</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">جزوی طور پر دستخط Ø´Ø¯Û Ø¨Ù¹ کوائن ٹرانزیکشن لوڈ کریں۔</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation type="unfinished">کلپ بورڈ سے جزوی طور پر دستخط Ø´Ø¯Û Ø¨Ù¹ کوائن ٹرانزیکشن لوڈ کریں۔</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">نوڈ ونڈو</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation type="unfinished">نوڈ ڈیبگنگ اور تشخیصی کنسول کھولیں۔</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished">اور بھیجنے والے پتے</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished">اور پتے وصول کرنا</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation type="unfinished">بٹ کوائن کا یو۔آر۔آئی۔ کھولیں</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation type="unfinished">والیٹ کھولیں</translation>
+ </message>
+ <message>
+ <source>Open a wallet</source>
+ <translation type="unfinished">والیٹ کھولیں</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">والیٹ بند کریں</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">تمام والیٹس بند کریں</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation type="unfinished">Ù…Ù…Ú©Ù†Û Ø¨Ù¹ کوائن کمانڈ لائن اختیارات Ú©Û’ ساتھ ÙÛرست حاصل کرنے Ú©Û’ لیے %1 مدد کا پیغام دکھائیں۔</translation>
+ </message>
+ <message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">قدروں کو چھپائیں</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">Ø¬Ø§Ø¦Ø²Û Ù¹ÛŒØ¨ میں اقدار Ú©Ùˆ ماسک کریں۔</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">Ù¾ÛÙ„Û’ سے Ø·Û’ Ø´Ø¯Û ÙˆØ§Ù„ÛŒÙ¹</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation type="unfinished">کوئی والیٹ دستیاب Ù†Ûیں Ûیں۔</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">والیٹ کا نام</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">اور ونڈو</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation type="unfinished">بغور Ø¬Ø§Ø¦Ø²Û Ù„ÛŒÙ†Ø§</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation type="unfinished">مین ونڈو</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation type="unfinished">'%1'کلائنٹ</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -485,42 +679,477 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">مزید کارروائی کے لیے کلک کریں۔</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">پیئرز ٹیب دکھائیں۔</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">نیٹ ورک Ú©ÛŒ سرگرمی Ú©Ùˆ غیر Ùعال کریں۔</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">نیٹ ورک Ú©ÛŒ سرگرمی Ú©Ùˆ Ùعال کریں۔</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">خرابی:%1</translation>
</message>
- </context>
+ <message>
+ <source>Warning: %1</source>
+ <translation type="unfinished">1%1 انتباÛ</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation type="unfinished">1%1' تاریخ۔
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation type="unfinished">1%1' مقدار
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation type="unfinished">1%1' والیٹ
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation type="unfinished">1 %1'قسم
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation type="unfinished">1%1'لیبل
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation type="unfinished">1%1' پتÛ
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation type="unfinished">بھیجی گئی ٹرانزیکشن</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation type="unfinished">آنے والی ٹرانزیکشن</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation type="unfinished">Ø¯Ø±Ø¬Û Ø¨Ù†Ø¯ÛŒ کا تعین کرنے والی ایچ۔ڈی کلیدی جنریشن &lt;b&gt;Ùعال&lt;/b&gt; ÛÛ’</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">Ø¯Ø±Ø¬Û Ø¨Ù†Ø¯ÛŒ کا تعین کرنے والی ایچ۔ ÚˆÛŒ کلیدی جنریشن&lt;b&gt; غیر Ùعال&lt;/b&gt; ÛÛ’</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">نجی کلید &lt;b&gt;غیر Ùعال &lt;b/&gt;ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Original message:</source>
+ <translation type="unfinished">اصل پیغام:</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">رقم ظاÛر کرنے Ú©Û’ لیے یونٹ۔ دوسری اکائی Ú©Ùˆ منتخب کرنے Ú©Û’ لیے Ú©Ù„Ú© کریں۔</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation type="unfinished">سکے کا انتخاب</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation type="unfinished">مقدار:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">بائٹس:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation type="unfinished">رقم:</translation>
</message>
<message>
+ <source>Fee:</source>
+ <translation type="unfinished">Ùیس:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">Ù†Û Ûونے Ú©Û’ برابر</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">Ùیس Ú©Û’ بعد:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">تبدیلی:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation type="unfinished">سب کو غیر منتخب کریں</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation type="unfinished">ٹری موڈ</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation type="unfinished">ÙÛرست موڈ</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation type="unfinished">رقم</translation>
</message>
<message>
+ <source>Received with label</source>
+ <translation type="unfinished">لیبل Ú©Û’ ساتھ موصول Ûوا۔</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation type="unfinished">پتے Ú©Û’ ساتھ موصول Ûوا۔</translation>
+ </message>
+ <message>
<source>Date</source>
<translation type="unfinished">تاریخ</translation>
</message>
<message>
+ <source>Confirmations</source>
+ <translation type="unfinished">تصدیقات</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">تصدیق شدÛ</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">رقم کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">ایڈریس کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">کاپی اور لیبل</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">کاپی اور رقم</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">غیر خرچ Ø´Ø¯Û Ø¢Ø¤Ù¹ پٹ بند کریں</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">غیر خرچ Ø´Ø¯Û Ú©Ú¾ÙˆÙ„ÛŒÚº</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">مقدار کاپی کریں</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Ùیس کاپی کریں</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Ùیس Ú©Û’ بعد کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">بائٹس کاپی کریں</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">باقی Ø´Ø¯Û Ú©Ø§Ù¾ÛŒ کریں</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">تبدیلی کاپی کریں</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation type="unfinished">مقÙÙ„'%1</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation type="unfinished">جی Ûاں</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation type="unfinished">Ù†Ûیں</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation type="unfinished">ÛŒÛ Ù„ÛŒØ¨Ù„ سرخ ÛÙˆ جاتا ÛÛ’ اگر کوئی وصول Ú©Ù†Ù†Ø¯Û Ù…ÙˆØ¬ÙˆØ¯Û Ú©Ù… سے Ú©Ù… مقرر Ú©Ø±Ø¯Û Ø­Ø¯ سے Ú©Ù… رقم وصول کرتا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation type="unfinished">مختل٠ÛÙˆ سکتے Ûیں%1 +/- ساتوشی ÙÛŒ ان پٹ۔</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(کوئی لیبل Ù†Ûیں)</translation>
</message>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation type="unfinished">%1 (%2)سے تبدیل کریں</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation type="unfinished">تبدیلی</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletActivity</name>
+ <message>
+ <source>Create Wallet</source>
+ <extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
+ <translation type="unfinished">والیٹ بنائیں</translation>
+ </message>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">والیٹ بنانا &lt;b&gt; %1&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation type="unfinished">والیٹ بنانا ناکام Ûوگیا۔</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation type="unfinished">والیٹ بنانے کےلئے انتباÛ</translation>
+ </message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">دستخط کنندگان Ú©ÛŒ ÙÛرست Ù†Ûیں بن سکتی</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>Open wallet failed</source>
+ <translation type="unfinished">والیٹ کھولنا ناکام ÛÙˆ گیا</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation type="unfinished">والیٹ کھولنے Ú©ÛŒ انتباÛ</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">Ù¾ÛÙ„Û’ سے Ø·Û’ Ø´Ø¯Û ÙˆØ§Ù„ÛŒÙ¹</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
+ <translation type="unfinished">والیٹ کھولیں</translation>
+ </message>
</context>
<context>
+ <name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">والیٹ بند کریں</translation>
+ </message>
+ <message>
+ <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
+ <translation type="unfinished">والیٹ Ú©Ùˆ Ø²ÛŒØ§Ø¯Û Ø¯ÛŒØ± تک بند کرنے Ú©Û’ نتیجے میں اگر کانٹ چھانٹ Ú©Ùˆ Ùعال کیا جاتا ÛÛ’ تو پوری چین Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û ÛÙ… Ø¢ÛÙ†Ú¯ کرنا Ù¾Ú‘ سکتا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">تمام والیٹس بند کریں</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation type="unfinished">کیا آپ واقعی تمام والیٹس بند کرنا چاÛتے Ûیں؟</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletDialog</name>
+ <message>
+ <source>Create Wallet</source>
+ <translation type="unfinished">والیٹ بنائیں</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation type="unfinished">والیٹ کا نام</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation type="unfinished">والیٹ</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation type="unfinished">والیٹ Ú©Ùˆ Ø®ÙÛŒÛ Ú©Ø±ÛŒÚºÛ” والیٹ Ú©Ùˆ آپ Ú©ÛŒ پسند Ú©Û’ پاسÙریز Ú©Û’ ساتھ Ø®ÙÛŒÛ Ú©ÛŒØ§ جائے گا۔</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation type="unfinished">والیٹ Ú©Ùˆ Ø®ÙÛŒÛ Ú©Ø±ÛŒÚºÛ”</translation>
+ </message>
+ <message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">اعلی درجے کے اختیارات</translation>
+ </message>
+ <message>
+ <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">اس والیٹ Ú©Û’ لیے نجی چابیوں Ú©Ùˆ غیر Ùعال کریں۔ غیر Ùعال نجی چابیوں والے والیٹ میں کوئی نجی چابیاں Ù†Ûیں ÛÙˆÚº Ú¯ÛŒ اور اس میں HD بیج یا درآمد Ø´Ø¯Û Ù†Ø¬ÛŒ چابیاں Ù†Ûیں ÛÙˆ سکتیں۔ ÛŒÛ ØµØ±Ù Ø¯ÛŒÚ©Ú¾Ù†Û’ والے والیٹ Ú©Û’ لیے مثالی ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation type="unfinished">نجی چابیاں غیر Ùعال کریں۔</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">ایک خالی والیٹ بنائیں۔ خالی والیٹ میں ابتدائی طور پر نجی چابیاں یا اسکرپٹ Ù†Ûیں Ûوتے Ûیں۔ نجی چابیاں اور پتے درآمد کیے جا سکتے Ûیں، یا بعد میں ایک HD بیج سیٹ کیا جا سکتا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation type="unfinished">خالی والیٹ بنائیں</translation>
+ </message>
+ <message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation type="unfinished">ScriptPubKeys کے انتظام کے لیے وضاحت کنندگان کا استعمال کریں۔</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">وضاحتی والیٹ</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">بیرونی دستخط کنندÛ</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation type="unfinished">بنائیں</translation>
+ </message>
+ <message>
+ <source>Compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished"> SQliteسپورٹ کے بغیر مرتب کیا گیا (ڈسکرپٹر والیٹس کے لیے درکار)</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">بیرونی دستخطی معاونت کے بغیر مرتب کیا گیا (بیرونی دستخط کے لیے درکار)</translation>
+ </message>
+</context>
+<context>
<name>EditAddressDialog</name>
<message>
+ <source>Edit Address</source>
+ <translation type="unfinished">ایڈریس میں ترمیم کریں۔</translation>
+ </message>
+ <message>
<source>&amp;Label</source>
<translation type="unfinished">Ú†Ù¹</translation>
</message>
<message>
+ <source>The label associated with this address list entry</source>
+ <translation type="unfinished">اس ایڈریس لسٹ Ú©Û’ اندراج سے ÙˆØ§Ø¨Ø³ØªÛ Ù„ÛŒØ¨Ù„</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation type="unfinished">اس ایڈریس لسٹ Ú©Û’ اندراج سے ÙˆØ§Ø¨Ø³ØªÛ Ù¾ØªÛÛ” اس میں صر٠ایڈریس بھیجنے Ú©Û’ لیے ترمیم Ú©ÛŒ جا سکتی ÛÛ’Û”</translation>
+ </message>
+ <message>
<source>&amp;Address</source>
<translation type="unfinished">پتÛ</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation type="unfinished">نیا بھیجنے کا پتÛ</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation type="unfinished">وصول Ú©Ù†Ù†Ø¯Û Ø§ÛŒÚˆØ±ÛŒØ³ میں ترمیم کریں۔</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation type="unfinished">بھیجنے کے پتے میں ترمیم کریں۔</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">والیٹ Ú©Ùˆ غیر مقÙÙ„ Ù†Ûیں کیا جا سکا۔</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation type="unfinished">نئی کلیدی نسل ناکام Ûوگئی۔</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation type="unfinished">ایک نئی ڈیٹا ڈائرکٹری بنائی جائے گی۔</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation type="unfinished">نام</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation type="unfinished">پاتھ Ù¾ÛÙ„Û’ سے موجود ÛÛ’ØŒ اور ڈائرکٹری Ù†Ûیں ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation type="unfinished">ÛŒÛاں ڈیٹا ڈائرکٹری Ù†Ûیں بن سکتی۔</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
+ <message>
+ <source>Bitcoin</source>
+ <translation type="unfinished">بٹ کوائن</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
<message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
@@ -530,32 +1159,710 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation type="unfinished">والیٹ بھی اس ڈائرکٹری میں محÙوظ کیا جائے گا۔</translation>
+ </message>
+ <message>
<source>Error</source>
<translation type="unfinished">نقص</translation>
</message>
+ <message>
+ <source>Welcome</source>
+ <translation type="unfinished">خوش آمدید</translation>
+ </message>
+ <message>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">بلاک چین اسٹوریج کو محدود کریں۔</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">اس ترتیب Ú©Ùˆ واپس کرنے Ú©Û’ لیے پورے بلاکچین Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û ÚˆØ§Ø¤Ù† لوڈ کرنے Ú©ÛŒ ضرورت ÛÛ’Û” Ù¾ÛÙ„Û’ پوری چین Ú©Ùˆ ڈاؤن لوڈ کرنا اور بعد میں اسے کاٹنا تیز تر ÛÛ’Û” Ú©Ú†Ú¾ جدید خصوصیات Ú©Ùˆ غیر Ùعال کرتا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source> GB</source>
+ <translation type="unfinished">جی بی</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation type="unfinished">اگر آپ Ù†Û’ بلاک چین اسٹوریج Ú©Ùˆ محدود کرنے کا انتخاب کیا ÛÛ’ (کاٹنا)ØŒ تو تاریخی ڈیٹا Ú©Ùˆ ابھی بھی ڈاؤن لوڈ اور پروسیس کیا جانا چاÛیے، لیکن آپ Ú©Û’ ڈسک Ú©Û’ استعمال Ú©Ùˆ Ú©Ù… رکھنے Ú©Û’ لیے اسے بعد میں حذ٠کر دیا جائے گا۔</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation type="unfinished">Ù¾ÛÙ„Û’ سے Ø·Û’ Ø´Ø¯Û ÚˆÛŒÙ¹Ø§ ڈائرکٹری استعمال کریں۔</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation type="unfinished">اپنی مرضی کے مطابق ڈیٹا ڈائرکٹری کا استعمال کریں:</translation>
+ </message>
+</context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation type="unfinished">ورژن</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation type="unfinished">تقریبآ %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation type="unfinished">کمانڈ لائن کے اختیارات</translation>
+ </message>
+</context>
+<context>
+ <name>ShutdownWindow</name>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation type="unfinished">جب تک ÛŒÛ ÙˆÙ†ÚˆÙˆ غائب Ù†Û Ûوجائے کمپیوٹر Ú©Ùˆ بند Ù†Û Ú©Ø±ÛŒÚºÛ”</translation>
+ </message>
+</context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation type="unfinished">Ùارم</translation>
+ </message>
+ <message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation type="unfinished">ÛÙˆ سکتا ÛÛ’ Ø­Ø§Ù„ÛŒÛ Ù„ÛŒÙ† دین ابھی تک نظر Ù†Û Ø¢Ø¦Û’ØŒ اور اس ÙˆØ¬Û Ø³Û’ آپ Ú©Û’ والیٹ کا بیلنس غلط ÛÙˆ سکتا ÛÛ’Û” ÛŒÛ Ù…Ø¹Ù„ÙˆÙ…Ø§Øª درست ÛÙˆÚº Ú¯ÛŒ جب آپ Ú©Û’ والیٹ Ù†Û’ بٹ کوائن نیٹ ورک Ú©Û’ ساتھ مطابقت پذیری مکمل کر Ù„ÛŒ Ûو، جیسا Ú©Û Ø°ÛŒÙ„ میں تÙصیل ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation type="unfinished">ایسے بٹ کوائنز خرچ کرنے Ú©ÛŒ کوشش کرنا جو ابھی تک ظاÛر Ù†Û Ûونے والے لین دین سے متاثر ÛÙˆÚº نیٹ ورک Ú©Û’ ذریعے قبول Ù†Ûیں کیا جائے گا۔</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation type="unfinished">باقی بلاکس کی تعداد</translation>
+ </message>
+ <message>
+ <source>Unknown…</source>
+ <translation type="unfinished">نامعلوم</translation>
+ </message>
+ <message>
+ <source>calculating…</source>
+ <translation type="unfinished">حساب لگانا</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation type="unfinished">آخری بلاک کا وقت</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation type="unfinished">پیش رÙت</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation type="unfinished">ÙÛŒ Ú¯Ú¾Ù†Ù¹Û Ù¾ÛŒØ´ رÙت میں اضاÙÛ</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation type="unfinished">مطابقت پذیر Ûونے میں تخمینی وقت باقی ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation type="unfinished">چھپائیں</translation>
+ </message>
</context>
<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <source>Open bitcoin URI</source>
+ <translation type="unfinished">بٹ کوائن URI کھولیں۔</translation>
+ </message>
+ <message>
+ <source>URI:</source>
+ <translation type="unfinished">URI</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <extracomment>Tooltip text for button that allows you to paste an address that is in your clipboard.</extracomment>
+ <translation type="unfinished">کلپ بورڈ سے Ù¾ØªÛ Ú†Ø³Ù¾Ø§Úº کریں۔</translation>
+ </message>
+</context>
+<context>
<name>OptionsDialog</name>
<message>
+ <source>Options</source>
+ <translation type="unfinished">اختیارات</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation type="unfinished">اور مرکزی</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">کٹائی Ú©Ùˆ Ùعال کرنا لین دین Ú©Ùˆ Ø°Ø®ÛŒØ±Û Ú©Ø±Ù†Û’ Ú©Û’ لیے درکار ڈسک Ú©ÛŒ Ø¬Ú¯Û Ú©Ùˆ نمایاں طور پر Ú©Ù… کرتا ÛÛ’Û” تمام بلاکس اب بھی مکمل طور پر درست Ûیں۔ اس ترتیب Ú©Ùˆ واپس کرنے Ú©Û’ لیے پورے بلاکچین Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û ÚˆØ§Ø¤Ù† لوڈ کرنے Ú©ÛŒ ضرورت ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation type="unfinished">ڈیٹا بیس کیشے کا سائز</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation type="unfinished">اسکرپٹ اور تصدیقی دھاگوں کی تعداد</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation type="unfinished">پراکسی کا IP Ù¾ØªÛ (جیسے IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ </message>
+ <message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation type="unfinished">ÛŒÛ Ø¯Ú©Ú¾Ø§ØªØ§ ÛÛ’ Ú©Û Ú©ÛŒØ§ ÙراÛÙ… Ú©Ø±Ø¯Û ÚˆÛŒÙالٹ SOCKS5 پراکسی اس نیٹ ورک Ú©ÛŒ قسم Ú©Û’ ذریعے ساتھی تک Ù¾ÛÙ†Ú†Ù†Û’ Ú©Û’ لیے استعمال Ûوتی ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">ونڈو بند Ûونے پر ایپلیکیشن سے باÛر نکلنے Ú©Û’ بجائے چھوٹا کریں۔ جب ÛŒÛ Ø¢Ù¾Ø´Ù† Ùعال ÛÙˆ جائے گا تو مینو میں ایگزٹ Ú©Ùˆ منتخب کرنے Ú©Û’ بعد ÛÛŒ ایپلیکیشن بند ÛÙˆ جائے گی۔</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation type="unfinished">ترتیب والی Ùائل کھولیں۔</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation type="unfinished">کلائنٹ Ú©Û’ تمام اختیارات Ú©Ùˆ ÚˆÛŒÙالٹ پر Ø¯ÙˆØ¨Ø§Ø±Û ØªØ±ØªÛŒØ¨ دیں۔</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation type="unfinished">اور Ø¯ÙˆØ¨Ø§Ø±Û ØªØ±ØªÛŒØ¨ دینے Ú©Û’ اختیارات</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation type="unfinished">اور نیٹ ورک</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation type="unfinished">جی بی</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation type="unfinished">اس ترتیب Ú©Ùˆ واپس کرنے Ú©Û’ لیے پورے بلاکچین Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û ÚˆØ§Ø¤Ù† لوڈ کرنے Ú©ÛŒ ضرورت ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation type="unfinished">ماÛر</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation type="unfinished">سکے اور کنٹرول Ú©ÛŒ خصوصیات Ú©Ùˆ Ùعال کریں۔</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">اگر آپ غیر Ù…ØµØ¯Ù‚Û ØªØ¨Ø¯ÛŒÙ„ÛŒ Ú©Û’ اخراجات Ú©Ùˆ غیر Ùعال کرتے Ûیں، تو کسی لین دین Ú©ÛŒ تبدیلی Ú©Ùˆ اس وقت تک استعمال Ù†Ûیں کیا جا سکتا جب تک Ú©Û Ø§Ø³ لین دین Ú©ÛŒ Ú©Ù… از Ú©Ù… ایک تصدیق Ù†Û ÛÙˆÛ” اس سے ÛŒÛ Ø¨Ú¾ÛŒ متاثر Ûوتا ÛÛ’ Ú©Û Ø¢Ù¾ Ú©Û’ بیلنس کا حساب کیسے لیا جاتا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation type="unfinished">اور غیر Ù…ØµØ¯Ù‚Û ØªØ¨Ø¯ÛŒÙ„ÛŒ خرچ کریں۔</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">اور ونڈو</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">بیرونی دستخطی معاونت کے بغیر مرتب کیا گیا (بیرونی دستخط کے لیے درکار)</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation type="unfinished">Ù¾ÛÙ„Û’ سے Ø·Û’ شدÛ</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation type="unfinished">کوئی Ù†Ûیں</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
+ <translation type="unfinished">اختیارات Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û ØªØ±ØªÛŒØ¨ دینے Ú©ÛŒ تصدیق کریں۔</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
+ <translation type="unfinished">تبدیلیوں Ú©Ùˆ چالو کرنے Ú©Û’ لیے کلائنٹ Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û Ø´Ø±ÙˆØ¹ کرنا ضروری ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
+ <translation type="unfinished">کلائنٹ Ú©Ùˆ بند کر دیا جائے گا۔ کیا آپ Ø¢Ú¯Û’ بڑھنا چاÛتے Ûیں؟</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <extracomment>Window title text of pop-up box that allows opening up of configuration file.</extracomment>
+ <translation type="unfinished">Ú©Ù†Ùیگریشن Ú©Û’ اختیارات</translation>
+ </message>
+ <message>
<source>Error</source>
<translation type="unfinished">نقص</translation>
</message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation type="unfinished">اس تبدیلی Ú©Ùˆ کلائنٹ Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û Ø´Ø±ÙˆØ¹ کرنے Ú©ÛŒ ضرورت Ûوگی۔</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation type="unfinished">ÙراÛÙ… Ú©Ø±Ø¯Û Ù¾Ø±Ø§Ú©Ø³ÛŒ Ù¾ØªÛ ØºÙ„Ø· ÛÛ’Û”</translation>
+ </message>
+</context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation type="unfinished">Ùارم</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">ظاÛر Ú©ÛŒ گئی معلومات پرانی ÛÙˆ سکتی ÛÛ’Û” کنکشن قائم Ûونے Ú©Û’ بعد آپ کا والیٹ خود بخود بٹ کوائن نیٹ ورک Ú©Û’ ساتھ ÛÙ… Ø¢ÛÙ†Ú¯ Ûوجاتا ÛÛ’ØŒ لیکن ÛŒÛ Ø¹Ù…Ù„ ابھی مکمل Ù†Ûیں Ûوا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation type="unfinished">صر٠دیکھنے کے لیے:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation type="unfinished">دستیاب:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation type="unfinished">آپ کا Ù…ÙˆØ¬ÙˆØ¯Û Ù‚Ø§Ø¨Ù„ خرچ بیلنس</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation type="unfinished">زیر التواء</translation>
+ </message>
+ <message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation type="unfinished">Ú©Ù„ ٹرانزیکشنز جن Ú©ÛŒ تصدیق Ûونا باقی ÛÛ’ØŒ اور ابھی تک قابل خرچ بیلنس میں شمار Ù†Ûیں Ûوتے </translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation type="unfinished">خام</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation type="unfinished">کان Ú©Ù†ÛŒ کا توازن جو ابھی Ù¾Ø®ØªÛ Ù†Ûیں Ûوا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation type="unfinished">بیلنس</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation type="unfinished">Ú©Ù„:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation type="unfinished">آپ کا Ú©Ù„ Ù…ÙˆØ¬ÙˆØ¯Û Ø¨ÛŒÙ„Ù†Ø³</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation type="unfinished">صر٠دیکھنے والے ایڈریسز میں آپ کا Ù…ÙˆØ¬ÙˆØ¯Û Ø¨ÛŒÙ„Ù†Ø³</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation type="unfinished">قابل خرچ:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation type="unfinished">Ø­Ø§Ù„ÛŒÛ Ù„ÛŒÙ† دین</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation type="unfinished">صر٠دیکھنے والے پتوں پر غیر تصدیق Ø´Ø¯Û Ù„ÛŒÙ† دین</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation type="unfinished">صر٠دیکھنے Ú©Û’ پتوں میں Ú©Ù„ Ù…ÙˆØ¬ÙˆØ¯Û Ø¨ÛŒÙ„Ù†Ø³</translation>
+ </message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation type="unfinished">Ø¬Ø§Ø¦Ø²Û Ù¹ÛŒØ¨ Ú©Û’ لیے پرائیویسی موڈ Ú©Ùˆ Ùعال کر دیا گیا ÛÛ’Û” اقدار Ú©Ùˆ Ûٹانے Ú©Û’ لیے، سیٹنگز-&gt;ماسک ویلیوز Ú©Ùˆ غیر چیک کریں۔</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation type="unfinished">کلپ بورڈ پر کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>Save…</source>
+ <translation type="unfinished">محÙوظ کریں۔</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation type="unfinished">بند کریں</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation type="unfinished">لین دین لوڈ کرنے میں ناکام:%1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation type="unfinished">لین دین پر دستخط کرنے میں ناکام:%1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation type="unfinished">مزید ان پٹ پر دستخط Ù†Ûیں ÛÙˆ سکے۔</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation type="unfinished">لین دین کا ڈیٹا محÙوظ کریں۔</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation type="unfinished">کل رقم</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation type="unfinished">یا</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation type="unfinished">لین دین Ú©Ùˆ ابھی بھی دستخط Ú©ÛŒ ضرورت ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation type="unfinished">(لیکن ÛŒÛ ÙˆØ§Ù„ÛŒÙ¹ لین دین پر دستخط Ù†Ûیں کر سکتا۔)</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation type="unfinished">لین دین Ú©ÛŒ حیثیت نامعلوم ÛÛ’Û”</translation>
+ </message>
+</context>
+<context>
+ <name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation type="unfinished">ادائیگی کی درخواست کی خرابی۔</translation>
+ </message>
+ <message>
+ <source>Cannot process payment request because BIP70 is not supported.
+Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
+If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation type="unfinished">ادائیگی Ú©ÛŒ درخواست پر کارروائی Ù†Ûیں Ú©ÛŒ جا سکتی Ú©ÛŒÙˆÙ†Ú©Û BIP70 تعاون یاÙØªÛ Ù†Ûیں ÛÛ’Û” BIP70 میں سیکورٹی Ú©ÛŒ وسیع خامیوں Ú©ÛŒ ÙˆØ¬Û Ø³Û’ ÛŒÛ Ù¾Ø±Ø²ÙˆØ± Ù…Ø´ÙˆØ±Û Ø¯ÛŒØ§ جاتا ÛÛ’ Ú©Û ÙˆØ§Ù„ÛŒÙ¹ Ú©Ùˆ تبدیل کرنے Ú©Û’ لیے کسی بھی تاجر Ú©ÛŒ Ûدایات Ú©Ùˆ نظر انداز کر دیا جائے۔ اگر آپ Ú©Ùˆ ÛŒÛ Ø®Ø±Ø§Ø¨ÛŒ موصول ÛÙˆ رÛÛŒ ÛÛ’ تو آپ Ú©Ùˆ مرچنٹ سے BIP21 مطابقت پذیر URI ÙراÛÙ… کرنے Ú©ÛŒ درخواست کرنی چاÛیے۔</translation>
+ </message>
</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>User Agent</source>
+ <extracomment>Title of Peers Table column which contains the peer's User Agent string.</extracomment>
+ <translation type="unfinished">صار٠ایجنٹ</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <extracomment>Title of Peers Table column which indicates the current latency of the connection with the peer.</extracomment>
+ <translation type="unfinished">پنگ</translation>
+ </message>
+ <message>
+ <source>Peer</source>
+ <extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
+ <translation type="unfinished">Ùریق</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
+ <translation type="unfinished">بھیجا</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <extracomment>Title of Peers Table column which indicates the total amount of network information we have received from the peer.</extracomment>
+ <translation type="unfinished">موصول Ûوا۔</translation>
+ </message>
+ <message>
<source>Address</source>
<extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
<translation type="unfinished">پتÛ</translation>
</message>
+ <message>
+ <source>Type</source>
+ <extracomment>Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</extracomment>
+ <translation type="unfinished">قسم</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <extracomment>Title of Peers Table column which states the network the peer connected through.</extracomment>
+ <translation type="unfinished">نیٹ ورک</translation>
+ </message>
+ </context>
+<context>
+ <name>QRImageWidget</name>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">اور تصویر محÙوظ کریں…</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation type="unfinished">اور تصویر کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation type="unfinished">کیو آر Ú©ÙˆÚˆ محÙوظ کریں۔</translation>
+ </message>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>&amp;Information</source>
+ <translation type="unfinished">اور معلومات</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation type="unfinished">آغاز کا وقت</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation type="unfinished">نیٹ ورک</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation type="unfinished">نام</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation type="unfinished">رابطوں کی تعداد</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation type="unfinished">بلاک چین</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation type="unfinished">لین دین Ú©ÛŒ Ù…ÙˆØ¬ÙˆØ¯Û ØªØ¹Ø¯Ø§Ø¯</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation type="unfinished">استعمال یاد داشت</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation type="unfinished">والیٹ</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation type="unfinished">(کوئی Ù†Ûیں)</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation type="unfinished">موصول Ûوا۔</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation type="unfinished">بھیجا</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation type="unfinished">اور Ùریق</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation type="unfinished">Ù…Ù…Ù†ÙˆØ¹Û Ùریقوں</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation type="unfinished">تÙصیلی معلومات دیکھنے Ú©Û’ لیے Ùریق کا انتخاب کریں۔</translation>
+ </message>
+ <message>
+ <source>Starting Block</source>
+ <translation type="unfinished">شروع Ûونے والا بلاک</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation type="unfinished">مطابقت پذیر بلاکس</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation type="unfinished">صار٠ایجنٹ</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">نوڈ ونڈو</translation>
+ </message>
+ <message>
+ <source>Current block height</source>
+ <translation type="unfinished">Ù…ÙˆØ¬ÙˆØ¯Û Ø¨Ù„Ø§Ú© Ú©ÛŒ اونچائی</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation type="unfinished">Ùونٹ کا سائز Ú©Ù… کریں۔</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation type="unfinished">Ùونٹ سائز میں اضاÙÛ Ú©Ø±ÛŒÚº</translation>
+ </message>
+ <message>
+ <source>Permissions</source>
+ <translation type="unfinished">اجازتیں</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation type="unfinished">خدمات</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation type="unfinished">کنکشن کا وقت</translation>
+ </message>
+ <message>
+ <source>Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
+ <translation type="unfinished">اس Ùریق Ú©ÛŒ جانب سے ابتدائی درستگی Ú©ÛŒ جانچ پڑتال کرنے والا ایک نیا بلاک موصول Ûونے Ú©Û’ بعد گزرا Ûوا وقت۔</translation>
+ </message>
+ <message>
+ <source>Last Block</source>
+ <translation type="unfinished">آخری بلاک</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation type="unfinished">آخری بھیجا۔</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation type="unfinished">آخری موصول</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation type="unfinished">آخری بلاک کا وقت</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation type="unfinished">Ú©Ù„</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation type="unfinished">کنسول صا٠کریں۔</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation type="unfinished">میں:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation type="unfinished">باÛر:</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">ایڈریس کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation type="unfinished">اور منقطع کریں۔</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation type="unfinished">نیٹ ورک Ú©ÛŒ سرگرمی غیر Ùعال ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation type="unfinished">جی Ûاں</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation type="unfinished">Ù†Ûیں</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation type="unfinished">Ú©Ùˆ</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation type="unfinished">سے</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation type="unfinished">کے لیے پابندی</translation>
+ </message>
+ <message>
+ <source>Never</source>
+ <translation type="unfinished">کبھی Ù†Ûیں</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation type="unfinished">نامعلوم</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Amount:</source>
+ <translation type="unfinished">اور رقم</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation type="unfinished">اور لیبل</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation type="unfinished">اور پیغام</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">ادائیگی Ú©ÛŒ درخواست Ú©Û’ ساتھ منسلک کرنے Ú©Û’ لیے ایک اختیاری پیغام، جو درخواست Ú©Û’ کھلنے پر ظاÛر Ûوگا۔ نوٹ: پیغام بٹ کوائن نیٹ ورک پر ادائیگی Ú©Û’ ساتھ Ù†Ûیں بھیجا جائے گا۔</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation type="unfinished">نئے وصول Ú©Ù†Ù†Ø¯Û Ù¾ØªÛ’ Ú©Û’ ساتھ منسلک کرنے Ú©Û’ لیے ایک اختیاری لیبل۔</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation type="unfinished">درخواست کرنے Ú©Û’ لیے ایک اختیاری رقم۔ کسی مخصوص رقم Ú©ÛŒ درخواست Ù†Û Ú©Ø±Ù†Û’ Ú©Û’ لیے اسے خالی یا صÙر Ú†Ú¾ÙˆÚ‘ دیں۔</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">وصول کرنے والے نئے پتے Ú©Û’ ساتھ منسلک کرنے Ú©Û’ لیے ایک اختیاری لیبل (آپ Ú©ÛŒ طر٠سے رسید Ú©ÛŒ شناخت Ú©Û’ لیے استعمال کیا جاتا ÛÛ’)Û” ÛŒÛ Ø§Ø¯Ø§Ø¦ÛŒÚ¯ÛŒ Ú©ÛŒ درخواست Ú©Û’ ساتھ بھی منسلک ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation type="unfinished">ایک اختیاری پیغام جو ادائیگی Ú©ÛŒ درخواست Ú©Û’ ساتھ منسلک ÛÛ’ اور بھیجنے والے Ú©Ùˆ دکھایا جا سکتا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation type="unfinished">اور وصول کرنے کا نیا Ù¾ØªÛ Ø¨Ù†Ø§Ø¦ÛŒÚº</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation type="unfinished">صاÙ</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">ایڈریس کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">کاپی اور لیبل</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">کاپی اور رقم</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">والیٹ Ú©Ùˆ غیر مقÙÙ„ Ù†Ûیں کیا جا سکا۔</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
+ <source>Request payment to …</source>
+ <translation type="unfinished">ادائیگی کی درخواست کریں…</translation>
+ </message>
+ <message>
+ <source>Address:</source>
+ <translation type="unfinished">پتÛ:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation type="unfinished">رقم:</translation>
</message>
<message>
+ <source>Label:</source>
+ <translation type="unfinished">لیبل</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation type="unfinished">پیغام</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">پرس:</translation>
</message>
@@ -563,6 +1870,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Copy &amp;Address</source>
<translation type="unfinished">کاپی پتÛ</translation>
</message>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">اور تصویر محÙوظ کریں…</translation>
+ </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -575,24 +1886,219 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">لیبل</translation>
</message>
<message>
+ <source>Message</source>
+ <translation type="unfinished">پیغام</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(کوئی لیبل Ù†Ûیں)</translation>
</message>
- </context>
+ <message>
+ <source>Requested</source>
+ <translation type="unfinished">درخواست کی۔</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
+ <source>Send Coins</source>
+ <translation type="unfinished">سکے بھیجیں۔</translation>
+ </message>
+ <message>
+ <source>Coin Control Features</source>
+ <translation type="unfinished">سکوں کے کنٹرول کی خصوصیات</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation type="unfinished">خود بخود منتخب</translation>
+ </message>
+ <message>
<source>Insufficient funds!</source>
<translation type="unfinished">ناکاÙÛŒ Ùنڈز</translation>
</message>
<message>
+ <source>Quantity:</source>
+ <translation type="unfinished">مقدار:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">بائٹس:</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation type="unfinished">رقم:</translation>
</message>
<message>
+ <source>Fee:</source>
+ <translation type="unfinished">Ùیس:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">Ùیس Ú©Û’ بعد:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">تبدیلی:</translation>
+ </message>
+ <message>
+ <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
+ <translation type="unfinished">اگر ÛŒÛ Ùعال ÛÛ’ØŒ لیکن تبدیلی کا Ù¾ØªÛ Ø®Ø§Ù„ÛŒ یا غلط ÛÛ’ØŒ تبدیلی Ú©Ùˆ نئے پیدا Ú©Ø±Ø¯Û Ù¾ØªÛ’ پر بھیج دیا جائے گا۔</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation type="unfinished">ٹرانزیکشن Ùیس:</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation type="unfinished">انتباÛ: Ùیس کا ØªØ®Ù…ÛŒÙ†Û ÙÛŒ الحال ممکن Ù†Ûیں ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation type="unfinished">ÙÛŒ کلو بائٹ(kb)</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation type="unfinished">چھپائیں</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation type="unfinished">تجویز کردÛ:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation type="unfinished">اپنی مرضی کے مطابق:</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation type="unfinished">ایک ساتھ متعدد وصول کنندگان کو بھیجیں۔</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">Ù†Û Ûونے Ú©Û’ برابر</translation>
+ </message>
+ <message>
+ <source>Choose…</source>
+ <translation type="unfinished">منتخب کریں…</translation>
+ </message>
+ <message>
+ <source>Hide transaction fee settings</source>
+ <translation type="unfinished">لین دین Ú©ÛŒ Ùیس Ú©ÛŒ ترتیبات چھپائیں۔</translation>
+ </message>
+ <message>
+ <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
+ <translation type="unfinished">بÛت Ú©Ù… Ùیس Ú©Û’ نتیجے میں کبھی بھی تصدیق Ù†Û Ûونے والی لین دین ÛÙˆ سکتی ÛÛ’ (ٹول ٹپ پڑھیں)</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation type="unfinished">تصدیقی وقت کا ÛدÙ:</translation>
+ </message>
+ <message>
<source>Balance:</source>
<translation type="unfinished">بیلنس:</translation>
</message>
+ <message>
+ <source>Confirm the send action</source>
+ <translation type="unfinished">بھیجنے کی کارروائی کی تصدیق کریں۔</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">مقدار کاپی کریں</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">رقم کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">Ùیس کاپی کریں</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">Ùیس Ú©Û’ بعد کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">بائٹس کاپی کریں</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">باقی Ø´Ø¯Û Ú©Ø§Ù¾ÛŒ کریں</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">تبدیلی کاپی کریں</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">Ù¾ÛÙ„Û’ اپنے Ûارڈویئر والیٹ Ú©Ùˆ جوڑیں۔</translation>
+ </message>
+ <message>
+ <source>To review recipient list click "Show Details…"</source>
+ <translation type="unfinished">وصول کنندگان Ú©ÛŒ ÙÛرست کا Ø¬Ø§Ø¦Ø²Û Ù„ÛŒÙ†Û’ Ú©Û’ لیے "تÙصیلات دکھائیں..." پر Ú©Ù„Ú© کریں۔</translation>
+ </message>
+ <message>
+ <source>Sign failed</source>
+ <translation type="unfinished">دستخط ناکام Ûوگیا</translation>
+ </message>
+ <message>
+ <source>External signer not found</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">بیرونی دستخط Ú©Ù†Ù†Ø¯Û Ù†Ûیں ملا</translation>
+ </message>
+ <message>
+ <source>External signer failure</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">بیرونی دستخط Ú©Ù†Ù†Ø¯Û Ú©ÛŒ ناکامی۔</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation type="unfinished">لین دین کا ڈیٹا محÙوظ کریں۔</translation>
+ </message>
+ <message>
+ <source>External balance:</source>
+ <translation type="unfinished">بیرونی توازن:</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation type="unfinished">یا</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
+ <translation type="unfinished">Ø¨Ø±Ø§Û Ú©Ø±Ù…ØŒ اپنے لین دین کا Ø¬Ø§Ø¦Ø²Û Ù„ÛŒÚºÛ”</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation type="unfinished">ٹرانزیکشن Ùیس</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation type="unfinished">کل رقم</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation type="unfinished">سکے بھیجنے کی تصدیق کریں۔</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation type="unfinished">وصول Ú©Ù†Ù†Ø¯Û Ú©Ø§ Ù¾ØªÛ Ø¯Ø±Ø³Øª Ù†Ûیں ÛÛ’Û” Ø¨Ø±Ø§Û Ú©Ø±Ù… Ø¯ÙˆØ¨Ø§Ø±Û Ú†ÛŒÚ© کریں۔</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation type="unfinished">ادا کرنے Ú©ÛŒ رقم 0 سے Ø²ÛŒØ§Ø¯Û Ûونی چاÛیے۔</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation type="unfinished">رقم آپ Ú©Û’ بیلنس سے Ø²ÛŒØ§Ø¯Û ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation type="unfinished">ڈپلیکیٹ Ù¾ØªÛ Ù…Ù„Ø§: پتے صر٠ایک بار استعمال کیے جائیں۔</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation type="unfinished">لین دین Ú©ÛŒ تخلیق ناکام ÛÙˆ گئی!</translation>
+ </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -601,16 +2107,150 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation type="unfinished">انتباÛ: غلط بٹ کوائن ایڈریس</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation type="unfinished">انتباÛ: نامعلوم تبدیلی کا پتÛ</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation type="unfinished">اپنی مرضی کے مطابق ایڈریس کی تبدیلی کی تصدیق کریں۔</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">آپ Ù†Û’ تبدیلی Ú©Û’ لیے جو Ù¾ØªÛ Ù…Ù†ØªØ®Ø¨ کیا ÛÛ’ ÙˆÛ Ø§Ø³ والیٹ کا Ø­ØµÛ Ù†Ûیں ÛÛ’Û” آپ Ú©Û’ والیٹ میں موجود کوئی بھی یا تمام Ùنڈز اس پتے پر بھیجے جا سکتے Ûیں۔ کیا آپ Ú©Ùˆ یقین ÛÛ’ØŸ</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(کوئی لیبل Ù†Ûیں)</translation>
</message>
</context>
<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <source>&amp;Label:</source>
+ <translation type="unfinished">اور لیبل</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation type="unfinished">Ù¾ÛÙ„Û’ استعمال Ø´Ø¯Û Ù¾ØªÛ Ú©Ø§ انتخاب کریں۔</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation type="unfinished">ادائیگی بھیجنے Ú©Û’ لیے بٹ کوائن کا پتÛ</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation type="unfinished">کلپ بورڈ سے Ù¾ØªÛ Ú†Ø³Ù¾Ø§Úº کریں۔</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation type="unfinished">اس اندراج Ú©Ùˆ Ûٹا دیں۔</translation>
+ </message>
+ <message>
+ <source>The amount to send in the selected unit</source>
+ <translation type="unfinished">منتخب یونٹ میں بھیجی جانے والی رقم</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">بھیجی جانے والی رقم سے Ùیس کاٹی جائے گی۔ وصول Ú©Ù†Ù†Ø¯Û Ú©Ùˆ اس سے Ú©Ù… بٹ کوائنز موصول ÛÙˆÚº Ú¯Û’ جو آپ رقم Ú©Û’ خانے میں داخل کریں Ú¯Û’Û” اگر متعدد وصول کنندگان Ú©Ùˆ منتخب کیا جاتا ÛÛ’ØŒ تو Ùیس Ú©Ùˆ برابر تقسیم کیا جاتا ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation type="unfinished">دستیاب بیلنس استعمال کریں۔</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation type="unfinished">پیغام</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <translation type="unfinished">استعمال Ø´Ø¯Û Ù¾ØªÙˆÚº Ú©ÛŒ ÙÛرست میں شامل کرنے Ú©Û’ لیے اس پتے Ú©Û’ لیے ایک لیبل درج کریں۔</translation>
+ </message>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation type="unfinished">دستخط - ایک پیغام پر دستخط / تصدیق کریں۔</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">آپ ÛŒÛ Ø«Ø§Ø¨Øª کرنے Ú©Û’ لیے اپنے پتوں Ú©Û’ ساتھ پیغامات/معاÛدوں پر دستخط کر سکتے Ûیں Ú©Û Ø¢Ù¾ ان پر بھیجے گئے بٹ کوائنز وصول کر سکتے Ûیں۔ Ûوشیار رÛیں Ú©Û Ú©Ø³ÛŒ بھی مبÛÙ… یا بے ترتیب پر دستخط Ù†Û Ú©Ø±ÛŒÚºØŒ Ú©ÛŒÙˆÙ†Ú©Û Ùریب دÛÛŒ Ú©Û’ حملے آپ Ú©Ùˆ اپنی شناخت پر دستخط کرنے Ú©Û’ لیے Ø¯Ú¾ÙˆÚ©Û Ø¯ÛŒÙ†Û’ Ú©ÛŒ کوشش کر سکتے Ûیں۔ صر٠مکمل تÙصیلی بیانات پر دستخط کریں جن سے آپ اتÙاق کرتے Ûیں۔</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation type="unfinished">پیغام پر دستخط کرنے Ú©Û’ لیے بٹ کوائن کا پتÛ</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation type="unfinished">Ù¾ÛÙ„Û’ استعمال Ø´Ø¯Û Ù¾ØªÛ Ú©Ø§ انتخاب کریں۔</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation type="unfinished">کلپ بورڈ سے Ù¾ØªÛ Ú†Ø³Ù¾Ø§Úº کریں۔</translation>
+ </message>
+ <message>
+ <source>Enter the message you want to sign here</source>
+ <translation type="unfinished">ÙˆÛ Ù¾ÛŒØºØ§Ù… درج کریں جس پر آپ دستخط کرنا چاÛتے Ûیں۔</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation type="unfinished">دستخط</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation type="unfinished">درج کیا گیا Ù¾ØªÛ ØºÙ„Ø· ÛÛ’Û”</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation type="unfinished">Ø¨Ø±Ø§Û Ú©Ø±Ù… Ù¾ØªÛ Ú†ÛŒÚ© کریں اور Ø¯ÙˆØ¨Ø§Ø±Û Ú©ÙˆØ´Ø´ کریں۔</translation>
+ </message>
+ <message>
+ <source>No error</source>
+ <translation type="unfinished">کوئی غلطی Ù†Ûیں۔</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation type="unfinished">پیغام پر دستخط ناکام ÛÙˆ گئے۔</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation type="unfinished">دستخط Ú©Ùˆ ÚˆÛŒ Ú©ÙˆÚˆ Ù†Ûیں کیا جا سکا۔</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation type="unfinished">Ø¨Ø±Ø§Û Ú©Ø±Ù… دستخط چیک کریں اور Ø¯ÙˆØ¨Ø§Ø±Û Ú©ÙˆØ´Ø´ کریں۔</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation type="unfinished">پیغام Ú©ÛŒ تصدیق ناکام ÛÙˆ گئی۔</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation type="unfinished">پیغام Ú©ÛŒ تصدیق ÛÙˆ گئی۔</translation>
+ </message>
+</context>
+<context>
<name>TransactionDesc</name>
<message>
<source>Date</source>
<translation type="unfinished">تاریخ</translation>
</message>
+ <message>
+ <source>From</source>
+ <translation type="unfinished">سے</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation type="unfinished">نامعلوم</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation type="unfinished">Ú©Ùˆ</translation>
+ </message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
@@ -619,6 +2259,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
+ <source>Transaction fee</source>
+ <translation type="unfinished">ٹرانزیکشن Ùیس</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation type="unfinished">پیغام</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation type="unfinished">رقم</translation>
</message>
@@ -630,6 +2278,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">تاریخ</translation>
</message>
<message>
+ <source>Type</source>
+ <translation type="unfinished">قسم</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">لیبل</translation>
</message>
@@ -641,15 +2293,39 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>TransactionView</name>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">ایڈریس کاپی کریں۔</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">کاپی اور لیبل</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">کاپی اور رقم</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">لین دین اور شناخت Ú©ÛŒ تÙصیلات(ID) کاپی کریں۔</translation>
+ </message>
+ <message>
<source>Comma separated file</source>
<extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
<translation type="unfinished">کوما سے الگ Ùائل</translation>
</message>
<message>
+ <source>Confirmed</source>
+ <translation type="unfinished">تصدیق شدÛ</translation>
+ </message>
+ <message>
<source>Date</source>
<translation type="unfinished">تاریخ</translation>
</message>
<message>
+ <source>Type</source>
+ <translation type="unfinished">قسم</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">لیبل</translation>
</message>
@@ -674,6 +2350,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>WalletModel</name>
+ <message>
+ <source>Send Coins</source>
+ <translation type="unfinished">سکے بھیجیں۔</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">Ù¾ÛÙ„Û’ سے Ø·Û’ Ø´Ø¯Û ÙˆØ§Ù„ÛŒÙ¹</translation>
+ </message>
+</context>
+<context>
<name>WalletView</name>
<message>
<source>&amp;Export</source>
diff --git a/src/qt/locale/bitcoin_uz.ts b/src/qt/locale/bitcoin_uz.ts
new file mode 100644
index 0000000000..31614bbdea
--- /dev/null
+++ b/src/qt/locale/bitcoin_uz.ts
@@ -0,0 +1,225 @@
+<TS version="2.1" language="uz">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation type="unfinished">Manzil yoki yorliqni o'zgartirish uchun o'ng tugmani bosing</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation type="unfinished">Yangi manzil yaratish</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation type="unfinished">Yangi</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation type="unfinished">Belgilangan manzilni tizim hotirasiga saqlash</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation type="unfinished">&amp;Ko'chirmoq</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation type="unfinished">Yo&amp;pish</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">Tanlangan manzilni ro'yhatdan o'chiring</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">Qidirish uchun manzil yoki yorliqni kiriting</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Joriy ichki oynaning ichidagi malumotlarni faylga yuklab olish</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">o'chirish</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">Tangalarni jo'natish uchun addressni tanlash</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">Tangalarni qabul qilib olish uchun manzilni tanlang</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation type="unfinished">tanlamoq</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation type="unfinished">Yuboriladigan manzillar</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation type="unfinished">Qabul qilinadigan manzillar</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">Quyidagilar to'lovlarni yuborish uchun Bitcoin manzillaringizdir. Har doim yuborishdan oldin yuborilayotgan tangalar sonini va qabul qiluvchi manzilni tekshirib ko'ring.</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Bular to'lovlarni qabul qilishingiz uchun sizning Bitcoin manzillaringizdir. Yangi qabul qiluvchi manzil yaratish uchun qabul qilish varag'idagi ''Yangi qabul qilish manzilini yaratish'' ustiga bosing. Faqat 'legacy' turdagi manzillar bilan xisobga kirish mumkin.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation type="unfinished">&amp;manzildan nusxa olish</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">Yorliqni ko'chirish</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">O'zgartirmoq</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation type="unfinished">Manzil ro'yhatini yuklab olish</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Vergul bilan ajratilgan fayl</translation>
+ </message>
+ </context>
+<context>
+ <name>QObject</name>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>BitcoinGUI</name>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(sufficient to restore backups %n day(s) old)</source>
+ <extracomment>Explanatory text on the capability of the current prune target.</extracomment>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Vergul bilan ajratilgan fayl</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Joriy ichki oynaning ichidagi malumotlarni faylga yuklab olish</translation>
+ </message>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts
index 0d9895fcee..a6f342ddad 100644
--- a/src/qt/locale/bitcoin_uz@Cyrl.ts
+++ b/src/qt/locale/bitcoin_uz@Cyrl.ts
@@ -70,6 +70,12 @@
<translation type="unfinished">Улар тўловларни жўнатиш учун Ñизнинг Bitcoin манзилларингиз. Доимо тангаларни жўнатишдан олдин Ñумма ва қабул қилувчи манзилни текшириб кўринг. </translation>
</message>
<message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">Улар тўловларни қабул қилиш учун Ñизнинг Bitcoin манзилларингиз. Янги манзилларни Ñратиш учун қабул қилиш варағидаги "Янги қабул қилиш манзилини Ñратиш" уÑтига боÑинг.
+Фақат 'legacy' туридаги манзиллар билан ҳиÑобга кириш мумкин.</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">Манзилдан &amp;нуÑха олиш</translation>
</message>
@@ -86,6 +92,11 @@
<translation type="unfinished">Манзил рўйхатини ÑкÑпорт қилиш</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Вергул билан ажратилган файл</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
<translation type="unfinished">Манзил рўйхатини %1.га Ñақлашда хатолик юз берди. Яна уриниб кўринг.</translation>
@@ -118,23 +129,27 @@
</message>
<message>
<source>Enter passphrase</source>
- <translation type="unfinished">Махфий Ñузни киритинг</translation>
+ <translation type="unfinished">Махфий Ñўзни киритинг</translation>
</message>
<message>
<source>New passphrase</source>
- <translation type="unfinished">Янги махфий Ñуз</translation>
+ <translation type="unfinished">Янги махфий Ñўз</translation>
</message>
<message>
<source>Repeat new passphrase</source>
- <translation type="unfinished">Янги махфий Ñузни такрорланг</translation>
+ <translation type="unfinished">Янги махфий Ñўзни такрорланг</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation type="unfinished">Махфий Ñўзни кўрÑатиш</translation>
</message>
<message>
<source>Encrypt wallet</source>
- <translation type="unfinished">Ҳамённи қодлаш</translation>
+ <translation type="unfinished">Ҳамённи шифрлаш</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation type="unfinished">Ушбу операциÑни амалга ошириш учун ҳамённи қулфдан чиқариш парол Ñўзини талаб қилади.</translation>
+ <translation type="unfinished">Ушбу операциÑни амалга ошириш учун ҳамённи қулфдан чиқариш махфий Ñўзини талаб қилади.</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -158,7 +173,19 @@
</message>
<message>
<source>Wallet encrypted</source>
- <translation type="unfinished">Ҳамёни кодланган</translation>
+ <translation type="unfinished">Ҳамён шифрланган</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation type="unfinished">Шифрланадиган ҳамён</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation type="unfinished">Ҳамёнингиз шифрланиш арафаÑида.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation type="unfinished">Ҳамёнингиз Ñнди шифрланади.</translation>
</message>
<message>
<source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
@@ -664,6 +691,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -806,10 +854,12 @@
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">ТаÑдиқлаш танловларини рад қилиш</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">Ўзгаришлар амалга ошиши учун мижозни қайта ишга тушириш талаб қилинади.</translation>
</message>
<message>
@@ -1379,10 +1429,6 @@
<source>Message:</source>
<translation type="unfinished">Хабар</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Тўлов олувчи:</translation>
- </message>
</context>
<context>
<name>SignVerifyMessageDialog</name>
@@ -1411,10 +1457,12 @@
<name>TransactionDesc</name>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/таÑдиқланмади</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 таÑдиқлашлар</translation>
</message>
<message>
@@ -1638,6 +1686,11 @@
<translation type="unfinished">Ўтказмалар тарихини ÑкÑпорт қилиш</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">Вергул билан ажратилган файл</translation>
+ </message>
+ <message>
<source>Confirmed</source>
<translation type="unfinished">ТаÑдиқланди</translation>
</message>
diff --git a/src/qt/locale/bitcoin_uz@Latn.ts b/src/qt/locale/bitcoin_uz@Latn.ts
index d18d84231f..50df95a8cf 100644
--- a/src/qt/locale/bitcoin_uz@Latn.ts
+++ b/src/qt/locale/bitcoin_uz@Latn.ts
@@ -14,6 +14,10 @@
<translation type="unfinished">&amp;Yangi</translation>
</message>
<message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation type="unfinished">Tanlangan manzilni tizim buferiga nusxalash</translation>
+ </message>
+ <message>
<source>&amp;Copy</source>
<translation type="unfinished">&amp;Nusxalash</translation>
</message>
@@ -22,10 +26,50 @@
<translation type="unfinished">Yo&amp;pish</translation>
</message>
<message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">Ro'yxatdan hozir tanlangan manzilni o'chiring</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">Qidirish uchun manzil yoki yorliqni kiriting</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Joriy yorliqdagi ma'lumotlarni faylga eksport qilish</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;Eksport</translation>
+ </message>
+ <message>
<source>&amp;Delete</source>
<translation type="unfinished">&amp;O'chirish</translation>
</message>
<message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">Coin yuborish uchun manzilni tanlang</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">Coinlarni qabul qilish uchun manzilni tanlang</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation type="unfinished">&amp;Tanlash</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation type="unfinished">Manzillarni yuborish</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation type="unfinished">Qabul qilish manzillari</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">Quyida to'lovlarni jo'natish uchun Bitcoin manzillaringiz. Coinlarni yuborishdan oldin har doim miqdor va qabul qilish manzilini tekshiring.</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation type="unfinished">&amp;Manzillarni nusxalash</translation>
</message>
@@ -42,6 +86,17 @@
</message>
</context>
<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">Haqiqatan ham hamyoningizni shifrlamoqchimisiz?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">Hamyon shifrlangan</translation>
+ </message>
+ </context>
+<context>
<name>QObject</name>
<message numerus="yes">
<source>%n second(s)</source>
@@ -87,6 +142,25 @@
</message>
</context>
<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation type="unfinished">HTTP serverni ishga tushirib bo'lmadi. Tafsilotlar uchun disk raskadrovka jurnaliga qarang.</translation>
+ </message>
+ <message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">Bloklar tekshirilmoqda…</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)…</source>
+ <translation type="unfinished">Hamyon(lar) tekshirilmoqda…</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation type="unfinished">Hamyonni qayta yozish kerak: bajarish uchun 1%s ni qayta ishga tushiring</translation>
+ </message>
+</context>
+<context>
<name>BitcoinGUI</name>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
@@ -107,6 +181,27 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
@@ -168,4 +263,15 @@
<translation type="unfinished">Manzil</translation>
</message>
</context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;Eksport</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">Joriy yorliqdagi ma'lumotlarni faylga eksport qilish</translation>
+ </message>
+ </context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts
index 8dd11d884f..0b41e8fe02 100644
--- a/src/qt/locale/bitcoin_vi.ts
+++ b/src/qt/locale/bitcoin_vi.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation type="unfinished">Nhấp chuột phải để sửa địa chỉ hoặc nhãn</translation>
+ <translation type="unfinished">Nhấn chuột phải để sửa địa chỉ hoặc nhãn</translation>
</message>
<message>
<source>Create a new address</source>
@@ -15,88 +15,41 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation type="unfinished">Sao chép các địa chỉ đã được chá»n vào bá»™ nhá»› tạm thá»i của hệ thống</translation>
+ <translation type="unfinished">Sao chép địa chỉ được chá»n vào bá»™ nhá»› tạm</translation>
</message>
<message>
<source>&amp;Copy</source>
<translation type="unfinished">&amp;Sao chép</translation>
</message>
<message>
- <source>C&amp;lose</source>
- <translation type="unfinished">Ä&amp;óng lại</translation>
- </message>
- <message>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished">Xóa địa chỉ Ä‘ang chá»n từ danh sách</translation>
+ <translation type="unfinished">Xoá địa chỉ được chá»n khá»i danh sách</translation>
</message>
<message>
- <source>Export the data in the current tab to a file</source>
- <translation type="unfinished">Xuất dữ liệu trong thẻ hiện tại ra file</translation>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">Nhập địa chỉ hoặc nhãn để tìm kiếm</translation>
</message>
<message>
<source>&amp;Export</source>
<translation type="unfinished">&amp;Xuất</translation>
</message>
<message>
- <source>&amp;Delete</source>
- <translation type="unfinished">&amp;Xóa</translation>
- </message>
- <message>
<source>Choose the address to send coins to</source>
- <translation type="unfinished">Chá»n địa chỉ để gá»­i coins đến</translation>
- </message>
- <message>
- <source>Choose the address to receive coins with</source>
- <translation type="unfinished">Chá»n địa chỉ để nhận coins vá»›i</translation>
- </message>
- <message>
- <source>C&amp;hoose</source>
- <translation type="unfinished">C&amp;há»n</translation>
+ <translation type="unfinished">Chá»n địa chỉ để gá»­i coin đến</translation>
</message>
<message>
<source>Sending addresses</source>
- <translation type="unfinished">Äịa chỉ Ä‘ang gá»­i</translation>
- </message>
- <message>
- <source>Receiving addresses</source>
- <translation type="unfinished">Äịa chỉ Ä‘ang nhận</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation type="unfinished">Äây là những địa chỉ Ä‘ang thá»±c hiện thanh toán. Luôn kiểm tra số lượng và địa chỉ nhận trÆ°á»›c khi gá»­i coins.</translation>
- </message>
- <message>
- <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
-Signing is only possible with addresses of the type 'legacy'.</source>
- <translation type="unfinished">Äây là các địa chỉ Bitcoin của bạn để nhận thanh toán. Sá»­ dụng nút 'Tạo địa chỉ nhận má»›i' trong tab nhận để tạo các địa chỉ má»›i. Chỉ có thể gán địa chỉ vá»›i các địa chỉ thuá»™c loại 'kế thừa'.</translation>
+ <translation type="unfinished">Äang gá»­i địa chỉ</translation>
</message>
<message>
- <source>&amp;Copy Address</source>
- <translation type="unfinished">&amp;Copy Äịa Chỉ</translation>
- </message>
- <message>
- <source>Copy &amp;Label</source>
- <translation type="unfinished">Copy &amp;Nhãn</translation>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">&amp;Chỉnh sửa</translation>
</message>
<message>
<source>Export Address List</source>
- <translation type="unfinished">Xuất List Äịa Chỉ</translation>
- </message>
- <message>
- <source>Comma separated file</source>
- <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
- <translation type="unfinished">Tệp tách dấu phẩy</translation>
+ <translation type="unfinished">Xuất danh sách địa chỉ</translation>
</message>
- <message>
- <source>There was an error trying to save the address list to %1. Please try again.</source>
- <extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
- <translation type="unfinished">Có lỗi khi đang save list địa chỉ đến %1. Vui lòng thử lại.</translation>
- </message>
- <message>
- <source>Exporting Failed</source>
- <translation type="unfinished">Xuất Thất Bại</translation>
- </message>
-</context>
+ </context>
<context>
<name>AddressTableModel</name>
<message>
@@ -109,46 +62,46 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(không nhãn)</translation>
+ <translation type="unfinished">(không có nhãn)</translation>
</message>
</context>
<context>
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
- <translation type="unfinished">Log Cụm Mật Khẩu</translation>
+ <translation type="unfinished">Hộp thoại cụm mật khẩu</translation>
</message>
<message>
<source>Enter passphrase</source>
- <translation type="unfinished">Nhập cụm mật khẩu</translation>
+ <translation type="unfinished">Nhập mật khẩu</translation>
</message>
<message>
<source>New passphrase</source>
- <translation type="unfinished">Cụm mật khẩu mới</translation>
+ <translation type="unfinished">Mật khẩu mới</translation>
</message>
<message>
<source>Repeat new passphrase</source>
- <translation type="unfinished">Lặp lại cụm mật khẩu mới</translation>
+ <translation type="unfinished">Nhập lại mật khẩu</translation>
</message>
<message>
<source>Show passphrase</source>
- <translation type="unfinished">Hiện cụm từ mật khẩu</translation>
+ <translation type="unfinished">Hiện mật khẩu</translation>
</message>
<message>
<source>Encrypt wallet</source>
- <translation type="unfinished">Ví mã hóa</translation>
+ <translation type="unfinished">Mã hoá ví</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation type="unfinished">Quá trình này cần cụm mật khẩu của bạn để mở khóa ví.</translation>
+ <translation type="unfinished">Hoạt động này cần mật khẩu ví của bạn để mở khoá ví.</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation type="unfinished">Mở khóa ví</translation>
+ <translation type="unfinished">Mở khoá ví</translation>
</message>
<message>
<source>Change passphrase</source>
- <translation type="unfinished">Äổi cụm mật khẩu</translation>
+ <translation type="unfinished">Äổi mật khẩu</translation>
</message>
<message>
<source>Confirm wallet encryption</source>
@@ -156,116 +109,87 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished">Cảnh báo: Nếu bạn mã hóa ví và mất cụm mật khẩu, bạn sẽ &lt;b&gt;MẤT TẤT CẢ BITCOIN&lt;/b&gt;!</translation>
+ <translation type="unfinished">Cảnh báo: Nếu bạn mã hóa ví và mất cụm mật khẩu, bạn sẽ &lt;b&gt;MẤT TẤT CẢ CÃC BITCOIN&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation type="unfinished">Bạn có chắc bạn muốn mã hóa ví của mình?</translation>
+ <translation type="unfinished">Bạn có chắc chắn muốn mã hoá ví không?</translation>
</message>
<message>
<source>Wallet encrypted</source>
- <translation type="unfinished">Ví đã được mã hóa</translation>
+ <translation type="unfinished">Äã mã hoá ví</translation>
</message>
<message>
<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">Nhập cụm từ mật khẩu má»›i cho ví Ä‘iện tá»­. Hãy sá»­ dụng cụm mật khẩu vá»›i mÆ°á»i hoặc nhiá»u hÆ¡n các ký tá»± ngẫu nhiên, hoặc nhiá»u hÆ¡n tám từ.</translation>
+ <translation type="unfinished">Nhập cụm mật khẩu má»›i cho ví.&lt;br/&gt;Vui lòng sá»­ dụng cụm mật khẩu gồm &lt;b&gt;mÆ°á»i ký tá»± ngẫu nhiên trở lên&lt;/b&gt;, hoặc &lt;b&gt;tám từ trở lên&lt;/b&gt;.</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
- <translation type="unfinished">Nhập cụm mật khẩu cũ và mật khẩu mới cho ví.</translation>
+ <translation type="unfinished">Nhập mật khẩu cũ và mật khẩu mới cho ví.</translation>
</message>
<message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation type="unfinished">Xin lÆ°u ý rằng mật mã hóa ví của bạn không thể bảo vệ hoàn toàn bitcoin của bạn khá»i đánh cắp bởi các phẩn má»m gián Ä‘iệp nhiá»…m vào máy tính của bạn.</translation>
+ <translation type="unfinished">Xin lÆ°u ý rằng mã hoá ví của bạn không thể bảo vá» hoàn toàn Bitcoin của bạn khá»i việc bị đánh cắp má»›i các phần má»m gián Ä‘iệp nhiá»…m vào máy tính của bạn.</translation>
</message>
<message>
<source>Wallet to be encrypted</source>
- <translation type="unfinished">Ví sẽ được mã hóa</translation>
+ <translation type="unfinished">Ví sẽ được mã hoá</translation>
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation type="unfinished">Ví của bạn sẽ được mã hóa.</translation>
+ <translation type="unfinished">Ví của bạn sẽ được mã hoá.</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation type="unfinished">Ví của bạn đã được mã hóa.</translation>
- </message>
- <message>
- <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
- <translation type="unfinished">QUAN TRỌNG: Bất cứ backup nào bạn từng làm trước đây từ ví của bạn nên được thay thế tạo mới, file mã hóa ví. Vì lý do bảo mật, các backup trước đây của các ví chưa mã hóa sẽ bị vô tác dụng ngay khi bạn bắt đầu sử dụng mới, ví đã được mã hóa.</translation>
+ <translation type="unfinished">Ví của bạn đã được mã hoá.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
- <translation type="unfinished">Quá trình mã hóa ví thất bại</translation>
+ <translation type="unfinished">Mã hoá ví thất bại</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation type="unfinished">Quá trình mã hóa ví thất bại do một lỗi nội tại. Ví của bạn vẫn chưa được mã hóa.</translation>
+ <translation type="unfinished">Mã hoá ví thất bại do lỗi nội bộ. Ví của bạn vẫn chưa được mã hoá.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
- <translation type="unfinished">Cụm mật khẩu được cung cấp không đúng.</translation>
+ <translation type="unfinished">Mật khẩu đã nhập không đúng.</translation>
</message>
- <message>
- <source>Wallet unlock failed</source>
- <translation type="unfinished">Mở khóa ví thất bại</translation>
- </message>
- <message>
- <source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation type="unfinished">Cụm mật khẩu đã nhập để giải mã ví không đúng.</translation>
- </message>
- <message>
- <source>Wallet passphrase was successfully changed.</source>
- <translation type="unfinished">Cụm mật khẩu thay đổi thành công.</translation>
- </message>
- <message>
- <source>Warning: The Caps Lock key is on!</source>
- <translation type="unfinished">Cảnh báo: chữ Viết Hoa đang bật!</translation>
- </message>
-</context>
+ </context>
<context>
- <name>BanTableModel</name>
+ <name>BitcoinApplication</name>
<message>
- <source>Banned Until</source>
- <translation type="unfinished">Cấm Äến</translation>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">Tệp cài đặt %1 có thể bị hư hại hoặc không hợp lệ.</translation>
</message>
-</context>
-<context>
- <name>BitcoinApplication</name>
<message>
<source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
<translation type="unfinished">Lỗi nghiêm trong. %1 không thể tiếp tục và sẽ thoát ra</translation>
</message>
- </context>
-<context>
- <name>QObject</name>
- <message>
- <source>Error: Specified data directory "%1" does not exist.</source>
- <translation type="unfinished">Error: Xác định data directory "%1" không tồn tại.</translation>
- </message>
- <message>
- <source>Error: Cannot parse configuration file: %1.</source>
- <translation type="unfinished">Lỗi: không thể phân giải tệp cài đặt cấu hình: %1.</translation>
- </message>
<message>
- <source>Amount</source>
- <translation type="unfinished">Số lượng</translation>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">Äã xảy ra lá»—i ná»™i bá»™. %1 sẽ cố gắng tiếp tục má»™t cách an toàn. Äây là má»™t lá»—i không mong muốn có thể được báo cáo nhÆ° mô tả bên dÆ°á»›i.</translation>
</message>
+</context>
+<context>
+ <name>QObject</name>
<message>
- <source>Enter a Bitcoin address (e.g. %1)</source>
- <translation type="unfinished">Nhập một Bitcoin address (e.g. %1)</translation>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">Bạn muốn đặt lại cài đặt vỠgiá trị mặc định hay hủy bỠmà không thực hiện thay đổi?</translation>
</message>
<message>
- <source>%1 h</source>
- <translation type="unfinished">%1 giá»</translation>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">Äã xảy ra lá»—i nghiêm trá»ng. Kiểm tra xem tệp cài đặt có thể ghi được không hoặc thá»­ chạy vá»›i -nosettings.</translation>
</message>
<message>
- <source>%1 m</source>
- <translation type="unfinished">%1 phút</translation>
+ <source>Error: %1</source>
+ <translation type="unfinished">Lá»—i: %1</translation>
</message>
<message>
- <source>%1 s</source>
- <translation type="unfinished">%1 giây</translation>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 vẫn chưa thoát ra một cách an toàn…</translation>
</message>
<message numerus="yes">
<source>%n second(s)</source>
@@ -297,10 +221,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<numerusform />
</translation>
</message>
- <message>
- <source>%1 and %2</source>
- <translation type="unfinished">%1 và %2</translation>
- </message>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
@@ -311,304 +231,215 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>bitcoin-core</name>
<message>
- <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
- <translation type="unfinished">Dá»± toán phí không thành công. Fallbackfee bị vô hiệu hóa. Äợi sau má»™t vài khối hoặc kích hoạt -fallbackfee.</translation>
- </message>
- <message>
- <source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
- <translation type="unfinished">Äây là phí giao dịch tối Ä‘a bạn phải trả (ngoài phí thông thÆ°á»ng) để Æ°u tiên việc tránh chi xài má»™t phần (partial spend) so vá»›i việc lá»±a chá»n đồng coin thông thÆ°á»ng.</translation>
- </message>
- <message>
- <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
- <translation type="unfinished">Cảnh báo: các khóa riêng tư được tìm thấy trong ví {%s} với khóa riêng tư không kích hoạt</translation>
- </message>
- <message>
- <source>A fatal internal error occurred, see debug.log for details</source>
- <translation type="unfinished">Lá»—i nghiêm trá»ng xảy ra, xem debug.log để biết chi tiết</translation>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">Không thể Ä‘á»c tệp cài đặt</translation>
</message>
<message>
- <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
- <translation type="unfinished">Không thể đặt -peerblockfilters mà không có -blockfilterindex.</translation>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">Không thể ghi tệp cài đặt</translation>
</message>
<message>
- <source>Cannot write to data directory '%s'; check permissions.</source>
- <translation type="unfinished">Không thể ghi vào thÆ° mục dữ liệu '%s'; kiểm tra lại quyá»n.</translation>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">Lá»—i khi Ä‘á»c%s! Dữ liệu giao dịch có thể bị thiếu hoặc không chính xác. Äang quét lại ví.</translation>
</message>
<message>
- <source>Config setting for %s only applied on %s network when in [%s] section.</source>
- <translation type="unfinished">Cài dặt thuộc tính cho %s chỉ có thể áp dụng cho mạng %s trong khi [%s] .</translation>
+ <source>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>
+ <translation type="unfinished">peers.dat (%s) không hợp lệ hoặc bị há»ng. Nếu bạn cho rằng đây là lá»—i, vui lòng báo cáo cho %s. Äể giải quyết vấn Ä‘á» này, bạn có thể di chuyển tệp (%s) ra khá»i (đổi tên, di chuyển hoặc xóa) để tạo tệp má»›i vào lần bắt đầu tiếp theo.</translation>
</message>
<message>
- <source>Could not find asmap file %s</source>
- <translation type="unfinished">Không tìm thấy tệp asmap %s</translation>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">Chế Ä‘á»™ rút gá»n không tÆ°Æ¡ng thích vá»›i -reindex-chainstate. Sá»­ dụng -reindex ở chế Ä‘á»™ đầy đủ.</translation>
</message>
<message>
- <source>Could not parse asmap file %s</source>
- <translation type="unfinished">Không Ä‘á»c được tệp asmap %s</translation>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">Chỉ mục khối db chứa má»™t 'txindex' kế thừa. Äể xóa dung lượng ổ Ä‘Ä©a bị chiếm dụng, hãy chạy -reindex đầy đủ, nếu không, hãy bá» qua lá»—i này. Thông báo lá»—i này sẽ không được hiển thị lại.</translation>
</message>
<message>
- <source>Disk space is too low!</source>
- <translation type="unfinished">Ổ đĩa còn quá ít</translation>
- </message>
- <message>
- <source>Error loading %s: Private keys can only be disabled during creation</source>
- <translation type="unfinished">Lỗi tải %s: Khóa riêng tư chỉ có thể không kích hoạt trong suốt quá trình tạo.</translation>
- </message>
- <message>
- <source>Error: Disk space is low for %s</source>
- <translation type="unfinished">Lá»—i: ÄÄ©a trống ít quá cho %s</translation>
- </message>
- <message>
- <source>Error: Keypool ran out, please call keypoolrefill first</source>
- <translation type="unfinished">Lá»—i: Keypool đã hết, vui lòng gá»i keypoolrefill trÆ°á»›c</translation>
- </message>
- <message>
- <source>Failed to rescan the wallet during initialization</source>
- <translation type="unfinished">Lỗi quét lại ví trong xuất quá trình khởi tạo</translation>
- </message>
- <message>
- <source>Failed to verify database</source>
- <translation type="unfinished">Lỗi xác nhận dữ liệu</translation>
+ <source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
+ <translation type="unfinished">Äây là phí giao dịch tối Ä‘a bạn phải trả (ngoài phí thông thÆ°á»ng) để Æ°u tiên việc tránh chi xài má»™t phần (partial spend) so vá»›i việc lá»±a chá»n đồng coin thông thÆ°á»ng.</translation>
</message>
<message>
- <source>Insufficient funds</source>
- <translation type="unfinished">Không đủ tiá»n</translation>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">Tìm thấy định dạng cÆ¡ sở dữ liệu trạng thái chuá»—i không được há»— trợ. Vui lòng khá»i Ä‘á»™ng lại vá»›i -reindex-chainstate. Việc này sẽ tái thiết lập cÆ¡ sở dữ liệu trạng thái chuá»—i.</translation>
</message>
<message>
- <source>Invalid P2P permission: '%s'</source>
- <translation type="unfinished">Quyá»n P2P không hợp lệ: '%s'</translation>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">Ví đã được tạo thành công. Loại ví Legacy đang bị phản đối và việc hỗ trợ mở các ví Legacy mới sẽ bị loại bỠtrong tương lai</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">Không có máy chủ proxy nào được chỉ định. Sử dụng -proxy =&lt;ip&gt; hoặc -proxy =&lt;ip:port&gt;.</translation>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">Không thể đặt -forcednsseed thành true khi đặt -dnsseed thành false.</translation>
</message>
<message>
- <source>Section [%s] is not recognized.</source>
- <translation type="unfinished">Mục [%s] không được nhìn nhận.</translation>
+ <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">Không thể hoàn tất nâng cấp -txindex được bắt đầu bởi phiên bản trước. Khởi động lại với phiên bản trước đó hoặc chạy -reindex đầy đủ.</translation>
</message>
<message>
- <source>Specified -walletdir "%s" does not exist</source>
- <translation type="unfinished">Thư mục ví được nêu -walletdir "%s" không tồn tại</translation>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s yêu cầu lắng nghe trên cổng %u. Cổng này được coi là "xấu" và do đó không có khả năng bất kỳ ngang hàng Bitcoin Core nào kết nối với nó. Xem doc/p2p-bad-ports.md để biết chi tiết và danh sách đầy đủ.</translation>
</message>
<message>
- <source>Specified -walletdir "%s" is a relative path</source>
- <translation type="unfinished">Chỉ định -walletdir "%s" là Ä‘Æ°á»ng dẫn tÆ°Æ¡ng đối</translation>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">reindex-chainstate tùy chá»n không tÆ°Æ¡ng thích vá»›i -blockfilterindex. Vui lòng tạp thá»i vô hiệu hóa blockfilterindex trong khi sá»­ dụng -reindex-chainstate, hoặc thay thế -reindex-chainstate bởi -reindex để tái thiết lập đẩy đủ tất cả các chỉ số.</translation>
</message>
<message>
- <source>Specified -walletdir "%s" is not a directory</source>
- <translation type="unfinished">Chỉ định -walletdir "%s" không phải là một thư mục</translation>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">reindex-chainstate tùy chá»n không tÆ°Æ¡ng thích vá»›i -coinstatsindex. Vui lòng tạp thá»i vô hiệu hóa coinstatsindex trong khi sá»­ dụng -reindex-chainstate, hoặc thay thế -reindex-chainstate bởi -reindex để tái thiết lập đẩy đủ tất cả các chỉ số.</translation>
</message>
<message>
- <source>Specified blocks directory "%s" does not exist.</source>
- <translation type="unfinished">Thư mục chứa các khối được chỉ ra "%s" không tồn tại</translation>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">reindex-chainstate tùy chá»n không tÆ°Æ¡ng thích vá»›i -txindex. Vui lòng tạp thá»i vô hiệu hóa txindex trong khi sá»­ dụng -reindex-chainstate, hoặc thay thế -reindex-chainstate bởi -reindex để tái thiết lập đẩy đủ tất cả các chỉ số.</translation>
</message>
<message>
- <source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation type="unfinished">Wallet sẽ hủy thanh toán nhỠhơn phí relay.</translation>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">Giả sá»­ hợp lệ: lần đồng bá»™ ví gần nhất vượt ra ngoài dữ liệu khả dụng của khối. Bạn cần phải chá» quá trình xác thá»±c ná»n tảng của chuối để tải vá» nhiá»u khối hÆ¡n.</translation>
</message>
<message>
- <source>This is the minimum transaction fee you pay on every transaction.</source>
- <translation type="unfinished">Äây là minimum transaction fee bạn pay cho má»—i transaction.</translation>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">Không thể cung cấp các kết nối cụ thể và yêu cầu addrman tìm các kết nối gửi đi cùng một lúc.</translation>
</message>
<message>
- <source>This is the transaction fee you will pay if you send a transaction.</source>
- <translation type="unfinished">Äây là transaction fee bạn sẽ pay nếu gá»­i transaction.</translation>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">Lá»—i khi tải %s: Ví ngÆ°á»i ký bên ngoài Ä‘ang được tải mà không có há»— trợ ngÆ°á»i ký bên ngoài được biên dịch</translation>
</message>
<message>
- <source>Transaction amounts must not be negative</source>
- <translation type="unfinished">Transaction amounts phải không âm</translation>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">Không thể đổi tên tệp ngang hàng không hợp lệ. Vui lòng di chuyển hoặc xóa nó và thử lại.</translation>
</message>
<message>
- <source>Transaction has too long of a mempool chain</source>
- <translation type="unfinished">Transaction có chuỗi mempool chain quá dài</translation>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">Äầu vào không được tìm thấy hoặc đã được sá»­ dụng</translation>
</message>
<message>
- <source>Transaction must have at least one recipient</source>
- <translation type="unfinished">Transaction phải có ít nhất má»™t ngÆ°á»i nhận</translation>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">Lắng nghe những kết nối thất bại sắp xảy ra (lắng nghe lỗi được trả vỠ%s)</translation>
</message>
<message>
- <source>Unable to create the PID file '%s': %s</source>
- <translation type="unfinished">Không thể tạo tệp PID '%s': %s</translation>
+ <source>Missing amount</source>
+ <translation type="unfinished">Số tiá»n còn thiếu</translation>
</message>
<message>
- <source>Unable to generate initial keys</source>
- <translation type="unfinished">Không thể tạo khóa ban đầu</translation>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">Thiếu dữ liệu giải quyết để ước tính quy mô giao dịch</translation>
</message>
<message>
- <source>Unable to generate keys</source>
- <translation type="unfinished">Không thể tạo khóa</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">Không có địa chỉ</translation>
</message>
<message>
- <source>Unknown -blockfilterindex value %s.</source>
- <translation type="unfinished">Không rõ giá trị -blockfilterindex %s.</translation>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">Chỉ số đầu ra thay đổi giao dịch nằm ngoài phạm vi</translation>
</message>
<message>
- <source>Unknown address type '%s'</source>
- <translation type="unfinished">Không biết địa chỉ kiểu '%s'</translation>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">Giao dịch cần thay đổi địa chỉ, nhưng chúng tôi không thể tạo địa chỉ đó.</translation>
</message>
<message>
- <source>Unknown change type '%s'</source>
- <translation type="unfinished">Không biết thay đổi kiểu '%s'</translation>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">Không có khả năng để phân bổ bộ nhớ cho -maxsigcachesize: '%s' MiB</translation>
</message>
<message>
- <source>Unknown network specified in -onlynet: '%s'</source>
- <translation type="unfinished">Unknown network được xác định trong -onlynet: '%s'</translation>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">Không thể parse -maxuploadtarget '%s</translation>
</message>
</context>
<context>
<name>BitcoinGUI</name>
<message>
- <source>&amp;Overview</source>
- <translation type="unfinished">&amp;Tổng quan</translation>
- </message>
- <message>
- <source>Show general overview of wallet</source>
- <translation type="unfinished">Hiển thị tổng quan ví</translation>
- </message>
- <message>
- <source>&amp;Transactions</source>
- <translation type="unfinished">&amp;Các Giao Dịch</translation>
- </message>
- <message>
- <source>Browse transaction history</source>
- <translation type="unfinished">Trình duyệt lịch sử giao dịch</translation>
- </message>
- <message>
- <source>E&amp;xit</source>
- <translation type="unfinished">T&amp;hoát</translation>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">&amp;Thu nhá»</translation>
</message>
<message>
- <source>Quit application</source>
- <translation type="unfinished">Äóng ứng dụng</translation>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;Mã hóa ví…</translation>
</message>
<message>
- <source>&amp;About %1</source>
- <translation type="unfinished">&amp;Khoảng %1</translation>
- </message>
- <message>
- <source>Show information about %1</source>
- <translation type="unfinished">Hiện thông tin khoảng %1</translation>
- </message>
- <message>
- <source>About &amp;Qt</source>
- <translation type="unfinished">Vá» &amp;Qt</translation>
- </message>
- <message>
- <source>Show information about Qt</source>
- <translation type="unfinished">Hiện thông tin vỠQt</translation>
- </message>
- <message>
- <source>Modify configuration options for %1</source>
- <translation type="unfinished">Sửa đổi tùy chỉnh cấu hình cho %1</translation>
- </message>
- <message>
- <source>Create a new wallet</source>
- <translation type="unfinished">Tạo một ví mới</translation>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">Mã hóa private key thuộc vỠví của bạn</translation>
</message>
<message>
- <source>Wallet:</source>
- <translation type="unfinished">Ví tiá»n</translation>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;Thay dổi Passphrase…</translation>
</message>
<message>
- <source>Network activity disabled.</source>
- <extracomment>A substring of the tooltip.</extracomment>
- <translation type="unfinished">Hoạt động mạng được vô hiệu.</translation>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished">Äăng ký lá»i nhắn vá»›i địa chỉ Bitcoin của bạn để chứng minh quyá»n sở hữu chúng</translation>
</message>
<message>
- <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
- <translation type="unfinished">Proxy là &lt;b&gt; cho phép &lt;/b&gt;: %1</translation>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;Xác minh tin nhắn…</translation>
</message>
<message>
- <source>Send coins to a Bitcoin address</source>
- <translation type="unfinished">Gửi coin đến một địa chỉ Bitcoin</translation>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">Xác minh lá»i nhắn để chắc chắn đã được đăng ký vá»›i địa chỉ Bitcoin xác định</translation>
</message>
<message>
- <source>Backup wallet to another location</source>
- <translation type="unfinished">Backup ví đến một địa chỉ khác</translation>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">Äóng ví…</translation>
</message>
<message>
- <source>Change the passphrase used for wallet encryption</source>
- <translation type="unfinished">Thay đổi cụm mật khẩu cho ví đã mã hóa</translation>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">Tạo ví…</translation>
</message>
<message>
- <source>&amp;Send</source>
- <translation type="unfinished">&amp;Gá»­i</translation>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">Äóng tất cả các ví…</translation>
</message>
<message>
- <source>&amp;Receive</source>
- <translation type="unfinished">&amp;Nhận</translation>
+ <source>&amp;File</source>
+ <translation type="unfinished">&amp;Tệp</translation>
</message>
<message>
- <source>Encrypt the private keys that belong to your wallet</source>
- <translation type="unfinished">Mã hóa private key thuộc vỠví của bạn</translation>
+ <source>&amp;Settings</source>
+ <translation type="unfinished">&amp;Cài đặt</translation>
</message>
<message>
- <source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation type="unfinished">Äăng ký lá»i nhắn vá»›i địa chỉ Bitcoin của bạn để chứng minh quyá»n sở hữu chúng</translation>
+ <source>&amp;Help</source>
+ <translation type="unfinished">&amp;Giúp đỡ</translation>
</message>
<message>
- <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation type="unfinished">Xác minh lá»i nhắn để chắc chắn đã được đăng ký vá»›i địa chỉ Bitcoin xác định</translation>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">Äồng bá»™ hóa tiêu Ä‘á» (%1%)...</translation>
</message>
<message>
- <source>Tabs toolbar</source>
- <translation type="unfinished">Các thanh công cụ</translation>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">Äồng bá»™ hóa vá»›i network...</translation>
</message>
<message>
- <source>Request payments (generates QR codes and bitcoin: URIs)</source>
- <translation type="unfinished">Yêu cầu thanh toán (tạo QR code và bitcoin: URIs)</translation>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">Lập chỉ mục các khối trên đĩa…</translation>
</message>
<message>
- <source>Show the list of used sending addresses and labels</source>
- <translation type="unfinished">Hiển thị danh sách các địa chỉ và nhãn đã dùng để gửi</translation>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">Xử lý khối trên đĩa…</translation>
</message>
<message>
- <source>Show the list of used receiving addresses and labels</source>
- <translation type="unfinished">Hiển thị danh sách các địa chỉ và nhãn đã dùng để nhận</translation>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">Lập chỉ mục lại các khối trên đĩa…</translation>
</message>
<message>
- <source>&amp;Command-line options</source>
- <translation type="unfinished">&amp;Tùy chỉnh Command-line</translation>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">Kết nối với các peer…</translation>
</message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>Äã xá»­ lý %n khối của lịch sá»­ giao dịch.</numerusform>
</translation>
</message>
<message>
- <source>%1 behind</source>
- <translation type="unfinished">%1 phia sau</translation>
- </message>
- <message>
- <source>Last received block was generated %1 ago.</source>
- <translation type="unfinished">Khối nhận cuối cùng đã được tạo %1.</translation>
- </message>
- <message>
- <source>Transactions after this will not yet be visible.</source>
- <translation type="unfinished">Các giao dịch sau giao dịch này sẽ không được hiển thị.</translation>
- </message>
- <message>
- <source>Error</source>
- <translation type="unfinished">Lá»—i</translation>
- </message>
- <message>
- <source>Warning</source>
- <translation type="unfinished">Cảnh báo</translation>
- </message>
- <message>
- <source>Information</source>
- <translation type="unfinished">Thông tin</translation>
- </message>
- <message>
- <source>Up to date</source>
- <translation type="unfinished">Äã cập nhật</translation>
+ <source>Catching up…</source>
+ <translation type="unfinished">Äang bắt kịp...</translation>
</message>
<message>
<source>Load Partially Signed Bitcoin Transaction</source>
<translation type="unfinished">Kết nối với mạng Bitcoin thông qua một proxy SOCKS5 riêng cho các dịch vụ Tor hành.</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">Tải PSBT từ &amp;khay nhớ tạm…</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">Tải một phần giao dịch Bitcoin đã ký từ khay nhớ tạm</translation>
</message>
@@ -645,429 +476,236 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Äông ví</translation>
</message>
<message>
- <source>Close all wallets</source>
- <translation type="unfinished">Äóng tất cả ví</translation>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">Khôi phục ví...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">Khôi phục ví từ tệp đã sao lưu</translation>
</message>
<message>
- <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
- <translation type="unfinished">Hiển thị %1 tin nhắn hỗ trợ để nhận được danh sách Bitcoin command-line khả dụng</translation>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">&amp;Giá trị mặt nạ</translation>
</message>
<message>
- <source>default wallet</source>
- <translation type="unfinished">ví mặc định</translation>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">Che các giá trị trong tab Tổng quan</translation>
</message>
<message>
- <source>No wallets available</source>
- <translation type="unfinished">Không có ví nào</translation>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">Tải bản sao lưu ví</translation>
</message>
<message>
- <source>Zoom</source>
- <translation type="unfinished">Phóng</translation>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">Khôi phục ví</translation>
</message>
<message>
- <source>Main Window</source>
- <translation type="unfinished">Màn hình chính</translation>
+ <source>Ctrl+M</source>
+ <translation type="unfinished">Nhấn Ctrl + M</translation>
</message>
<message>
- <source>%1 client</source>
- <translation type="unfinished">%1 khách</translation>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;Ẩn</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">Trìn&amp;h diễn</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nkết nối đang hoạt động với mạng lưới Bitcoin</numerusform>
</translation>
</message>
<message>
- <source>Warning: %1</source>
- <translation type="unfinished">Cảnh báo: %1</translation>
- </message>
- <message>
- <source>Date: %1
-</source>
- <translation type="unfinished">Ngày %1
-</translation>
- </message>
- <message>
- <source>Amount: %1
-</source>
- <translation type="unfinished">Số lượng: %1
-</translation>
- </message>
- <message>
- <source>Wallet: %1
-</source>
- <translation type="unfinished">Ví: %1
-</translation>
- </message>
- <message>
- <source>Type: %1
-</source>
- <translation type="unfinished">Loại: %1
-</translation>
- </message>
- <message>
- <source>Label: %1
-</source>
- <translation type="unfinished">Nhãn: %1
-</translation>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">Nhấp để có thêm hành động.</translation>
</message>
<message>
- <source>Address: %1
-</source>
- <translation type="unfinished">Äịa chỉ: %1
-</translation>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">Hiển thị tab ngang hàng</translation>
</message>
<message>
- <source>Sent transaction</source>
- <translation type="unfinished">Giao dịch đã gửi</translation>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">Tắt hoạt động mạng</translation>
</message>
<message>
- <source>Incoming transaction</source>
- <translation type="unfinished">Giao dịch đang nhận</translation>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">Bật hoạt động mạng</translation>
</message>
<message>
- <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
- <translation type="unfinished">Khởi tạo HD key &lt;b&gt;enabled&lt;/b&gt;</translation>
- </message>
- <message>
- <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation type="unfinished">Khởi tạo HD key &lt;b&gt;disabled&lt;/b&gt;</translation>
+ <source>Error: %1</source>
+ <translation type="unfinished">Lá»—i: %1</translation>
</message>
<message>
<source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation type="unfinished">Khóa riên tư &lt;b&gt;đã tắt&lt;/b&gt;</translation>
+ <translation type="unfinished">Khóa riêng tư &lt;b&gt;đã tắt&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
- <translation type="unfinished">Ví thì &lt;b&gt;encrypted&lt;/b&gt; và hiện tại &lt;b&gt;unlocked&lt;/b&gt;</translation>
+ <translation type="unfinished">Ví thì &lt;b&gt;được mã hóa &lt;/b&gt; và hiện tại &lt;b&gt;đã khóa&lt;/b&gt;</translation>
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation type="unfinished">Ví thì &lt;b&gt;encrypted&lt;/b&gt; và hiện tại &lt;b&gt;locked&lt;/b&gt;</translation>
+ <translation type="unfinished">Ví thì &lt;b&gt;được mã hóa &lt;/b&gt; và hiện tại &lt;b&gt;đã khóa&lt;/b&gt;</translation>
</message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
<message>
- <source>Original message:</source>
- <translation type="unfinished">Tin nhắn ban đầu:</translation>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">ÄÆ¡n vị để hiển thị số tiá»n. Nhấp để chá»n Ä‘Æ¡n vị khác.</translation>
</message>
</context>
<context>
<name>CoinControlDialog</name>
<message>
- <source>Coin Selection</source>
- <translation type="unfinished">Lá»±a chá»n Coin</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation type="unfinished">Số lượng:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation type="unfinished">Số lượng:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation type="unfinished">Phí:</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation type="unfinished">Rác:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation type="unfinished">Sau Phí:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation type="unfinished">Thay đổi:</translation>
- </message>
- <message>
- <source>(un)select all</source>
- <translation type="unfinished">(không)chá»n tất cả</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation type="unfinished">Số lượng</translation>
- </message>
- <message>
- <source>Received with label</source>
- <translation type="unfinished">Äã nhận vá»›i nhãn</translation>
- </message>
- <message>
- <source>Received with address</source>
- <translation type="unfinished">Äã nhận vá»›i địa chỉ</translation>
- </message>
- <message>
- <source>Date</source>
- <translation type="unfinished">Ngày</translation>
+ <source>Tree mode</source>
+ <translation type="unfinished">Chế độ Tree</translation>
</message>
<message>
- <source>Confirmations</source>
- <translation type="unfinished">Xác nhận</translation>
+ <source>List mode</source>
+ <translation type="unfinished">Chế độ List</translation>
</message>
<message>
- <source>Confirmed</source>
- <translation type="unfinished">Äã xác nhận</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation type="unfinished">Sao chép số lượng</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation type="unfinished">Sao chép số lượng</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation type="unfinished">Sao chép phí</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation type="unfinished">Sao chép sau phí</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation type="unfinished">Sao chép bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation type="unfinished">Sao chép rác</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation type="unfinished">Sao chép thay đổi</translation>
- </message>
- <message>
- <source>(%1 locked)</source>
- <translation type="unfinished">(%1 đã khóa)</translation>
- </message>
- <message>
- <source>yes</source>
- <translation type="unfinished">có</translation>
- </message>
- <message>
- <source>no</source>
- <translation type="unfinished">không</translation>
- </message>
- <message>
- <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation type="unfinished">Label này chuyển sang đỠnếu bất cứ giao dịch nhận nào có số lượng nhỠhơn ngưỡng dust.</translation>
- </message>
- <message>
- <source>Can vary +/- %1 satoshi(s) per input.</source>
- <translation type="unfinished">Có thể thay đổi +/-%1 satoshi(s) trên input.</translation>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">Sao chép giao dịch &amp;ID và chỉ mục đầu ra</translation>
</message>
<message>
<source>(no label)</source>
- <translation type="unfinished">(không nhãn)</translation>
- </message>
- <message>
- <source>change from %1 (%2)</source>
- <translation type="unfinished">change từ %1 (%2)</translation>
+ <translation type="unfinished">(không có nhãn)</translation>
</message>
</context>
<context>
<name>CreateWalletActivity</name>
<message>
- <source>Create Wallet</source>
- <extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
- <translation type="unfinished">Tạo Ví</translation>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">Có quá nhiá»u ngÆ°á»i ký từ bên ngoài được tìm thấy</translation>
</message>
+</context>
+<context>
+ <name>LoadWalletsActivity</name>
<message>
- <source>Create wallet failed</source>
- <translation type="unfinished">Tạo ví thất bại</translation>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">Tải ví</translation>
</message>
<message>
- <source>Create wallet warning</source>
- <translation type="unfinished">Cảnh báo khi tạo ví</translation>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">Äang tải ví…</translation>
</message>
- </context>
+</context>
<context>
<name>OpenWalletActivity</name>
<message>
- <source>Open wallet failed</source>
- <translation type="unfinished">Mở ví thất bại</translation>
- </message>
- <message>
- <source>Open wallet warning</source>
- <translation type="unfinished">Mở ví cảnh báo</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation type="unfinished">ví mặc định</translation>
- </message>
- <message>
<source>Open Wallet</source>
<extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
<translation type="unfinished">Mớ ví</translation>
</message>
</context>
<context>
- <name>WalletController</name>
+ <name>RestoreWalletActivity</name>
<message>
- <source>Close wallet</source>
- <translation type="unfinished">Äông ví</translation>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">Khôi phục ví</translation>
</message>
<message>
- <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
- <translation type="unfinished">Bạn có chắc bạn muốn đóng ví %1 ?</translation>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">Äang khôi phục ví &lt;b&gt;%1&lt;/b&gt;…</translation>
</message>
<message>
- <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
- <translation type="unfinished">Äóng ví thá»i gian dài sẽ dẫn đến phải đồng bá»™ hóa lại cả chuá»—i nếu cắt tỉa pruning được kích hoạt</translation>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">Khôi phục ví thất bại</translation>
</message>
<message>
- <source>Close all wallets</source>
- <translation type="unfinished">Äóng tất cả ví</translation>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">Cảnh báo khối phục ví</translation>
</message>
<message>
- <source>Are you sure you wish to close all wallets?</source>
- <translation type="unfinished">Bạn có chắc chắn muốn đóng tất cả ví không?</translation>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">Tin nhắn khôi phục ví</translation>
</message>
</context>
<context>
- <name>CreateWalletDialog</name>
- <message>
- <source>Create Wallet</source>
- <translation type="unfinished">Tạo Ví</translation>
- </message>
- <message>
- <source>Wallet Name</source>
- <translation type="unfinished">Tên Ví</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation type="unfinished">Ví</translation>
- </message>
- <message>
- <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
- <translation type="unfinished">Mật mã hóa ví. Ví sẽ được mật mã hóa với cụm mật khẩu của bạn.</translation>
- </message>
- <message>
- <source>Encrypt Wallet</source>
- <translation type="unfinished">Mật mã hóa ví</translation>
- </message>
- <message>
- <source>Advanced Options</source>
- <translation type="unfinished">Giao dịch thiếu một số thông tin vỠđầu vào.</translation>
- </message>
- <message>
- <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">Tắt các khóa cá nhân cho ví này. Các ví với khóa cá nhân tắt sẽ không có các khóa cá nhân và không thể có nhân HD hoặc nhập thêm khóa cá nhân. Việc này tốt cho các ví chỉ dùng để xem.</translation>
- </message>
- <message>
- <source>Disable Private Keys</source>
- <translation type="unfinished">Vô hiệu hóa khóa cá nhân</translation>
- </message>
+ <name>WalletController</name>
<message>
- <source>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>
- <translation type="unfinished">Tạo một ví trống. Ví trống không có các khóa cá nhân hay script ban đầu. Khóa cá nhân và địa chỉ có thể được nhập, hoặc một nhân HD có thể được thiết lập sau đó.</translation>
+ <source>Close wallet</source>
+ <translation type="unfinished">Äông ví</translation>
</message>
<message>
- <source>Make Blank Wallet</source>
- <translation type="unfinished">Tạo ví trống</translation>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation type="unfinished">Bạn có chắc chắn muốn đóng ví không &lt;i&gt;%1&lt;/i&gt;?</translation>
</message>
+ </context>
+<context>
+ <name>CreateWalletDialog</name>
<message>
<source>Use descriptors for scriptPubKey management</source>
- <translation type="unfinished">Không có máy chủ proxy nào được chỉ định. Sử dụng -proxy = &lt;ip&gt; hoặc -proxy = &lt;ip: port&gt;.</translation>
+ <translation type="unfinished">Sử dụng bộ mô tả để quản lý scriptPubKey</translation>
</message>
<message>
- <source>Descriptor Wallet</source>
- <translation type="unfinished">Mô tả ví</translation>
+ <source>Use an external signing device such as a hardware wallet. Configure the external signer script in wallet preferences first.</source>
+ <translation type="unfinished">Sá»­ dụng thiết bị ký bên ngoài chẳng hạn nhÆ° ví phần cứng. TrÆ°á»›c tiên, hãy định cấu hình tập lệnh ngÆ°á»i ký bên ngoài trong tùy chá»n ví.</translation>
</message>
<message>
- <source>Create</source>
- <translation type="unfinished">Tạo</translation>
+ <source>External signer</source>
+ <translation type="unfinished">NgÆ°á»i ký tên bên ngoài</translation>
</message>
<message>
- <source>Compiled without sqlite support (required for descriptor wallets)</source>
- <translation type="unfinished">Biên dịch cần hỗ trợ SQLite(Bắt buộc đối với mô tả ví)</translation>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Äược biên dịch mà không có há»— trợ ký bên ngoài (bắt buá»™c đối vá»›i ký bên ngoài)</translation>
</message>
- </context>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
- <source>&amp;Label</source>
- <translation type="unfinished">Nhãn dữ liệu</translation>
- </message>
- <message>
- <source>The label associated with this address list entry</source>
- <translation type="unfinished">Label liên kết với list address ban đầu này</translation>
- </message>
- <message>
- <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation type="unfinished">Label liên kết vá»›i list address ban đầu này. Äiá»u này chỉ được Ä‘iá»u chỉnh cho địa chỉ gá»­i.</translation>
- </message>
- <message>
- <source>&amp;Address</source>
- <translation type="unfinished">Äịa chỉ</translation>
- </message>
- <message>
- <source>New sending address</source>
- <translation type="unfinished">Address Ä‘ang gá»­i má»›i</translation>
+ <source>Edit Address</source>
+ <translation type="unfinished">Sửa địa chỉ</translation>
</message>
<message>
<source>Edit receiving address</source>
- <translation type="unfinished">Edit address đang nhận</translation>
+ <translation type="unfinished">Chỉnh sửa địa chỉ nhận</translation>
</message>
<message>
<source>Edit sending address</source>
- <translation type="unfinished">Edit address Ä‘ang gá»­i</translation>
- </message>
- <message>
- <source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation type="unfinished">Address đã nhập "%1" không valid Bitcoin address.</translation>
- </message>
- <message>
- <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
- <translation type="unfinished">Äịa chỉ "%1" đã tồn tại nhÆ° địa chỉ nhận vá»›i nhãn "%2" và vì vậy không thể thêm nhÆ° là địa chỉ gá»­i.</translation>
+ <translation type="unfinished">Chỉnh sửa địa chỉ gửi</translation>
</message>
- <message>
- <source>The entered address "%1" is already in the address book with label "%2".</source>
- <translation type="unfinished">Äịa chỉ nhập "%1" đã có trong sổ địa chỉ vá»›i nhãn "%2".</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation type="unfinished">Không thể unlock wallet.</translation>
- </message>
- <message>
- <source>New key generation failed.</source>
- <translation type="unfinished">Khởi tạo key mới thất bại.</translation>
- </message>
-</context>
-<context>
- <name>FreespaceChecker</name>
- <message>
- <source>A new data directory will be created.</source>
- <translation type="unfinished">Một danh mục dữ liệu mới sẽ được tạo.</translation>
- </message>
- <message>
- <source>name</source>
- <translation type="unfinished">tên</translation>
- </message>
- <message>
- <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
- <translation type="unfinished">Danh mục đã tồn tại. Thêm %1 nếu bạn dự định creat một danh mục mới ở đây.</translation>
- </message>
- <message>
- <source>Path already exists, and is not a directory.</source>
- <translation type="unfinished">Path đã tồn tại, và không là danh mục.</translation>
- </message>
- <message>
- <source>Cannot create data directory here.</source>
- <translation type="unfinished">Không thể create dữ liệu danh mục tại đây.</translation>
- </message>
-</context>
+ </context>
<context>
<name>Intro</name>
- <message>
- <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation type="unfinished">Ãt nhất %1 GB data sẽ được trữ tại danh mục này, và nó sẽ lá»›n theo thá»i gian.</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
- <message>
- <source>Approximately %1 GB of data will be stored in this directory.</source>
- <translation type="unfinished">Gần đúng %1 GB of data sẽ được lưu giữ trong danh mục này.</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
</message>
<message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
@@ -1077,1070 +715,295 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
- <source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation type="unfinished">%1 sẽ download và lưu trữ một bản copy của Bitcoin block chain.</translation>
- </message>
- <message>
- <source>The wallet will also be stored in this directory.</source>
- <translation type="unfinished">Wallet sẽ cùng được lưu giữ trong danh mục này.</translation>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation type="unfinished">Lỗi: Danh mục data xác định "%1" không thể được tạo.</translation>
</message>
<message>
- <source>Error: Specified data directory "%1" cannot be created.</source>
- <translation type="unfinished">Error: Danh mục data xác định "%1" không thể được tạo.</translation>
+ <source>Welcome</source>
+ <translation type="unfinished">Chào mừng</translation>
</message>
<message>
- <source>Error</source>
- <translation type="unfinished">Lá»—i</translation>
+ <source>Welcome to %1.</source>
+ <translation type="unfinished">Chào mừng bạn đến %1.</translation>
</message>
<message>
<source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
- <translation type="unfinished">Äây là lần đầu chÆ°Æ¡ng trình khởi chạy, bạn có thể chá»n nÆ¡i %1 sẽ lÆ°u trữ data.</translation>
+ <translation type="unfinished">Äây là lần đầu chÆ°Æ¡ng trình khởi chạy, bạn có thể chá»n nÆ¡i %1 sẽ lÆ°u trữ dữ liệu.</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">Khi bạn click OK, %1 sẽ bắt đầu download và process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</translation>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">Giới hạn lưu trữ chuỗi khối thành</translation>
</message>
<message>
<source>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>
- <translation type="unfinished">Äảo ngược lại thiết lập này yêu cầu download lại toàn bá»™ blockchain. Download toàn bá»™ blockchain trÆ°á»›c và loại nó sau đó sẽ nhanh hÆ¡n. Vô hiệu hóa má»™t số tính năng nâng cao.</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Äồng bá»™ hóa ban đầu này rất đòi há»i, và có thể phÆ¡i bày các sá»± cố vá» phần cứng vá»›i máy tính của bạn trÆ°á»›c đó đã không được chú ý. Má»—i khi bạn chạy %1, nó sẽ tiếp tục tải vá» nÆ¡i nó dừng lại.</translation>
- </message>
- <message>
- <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
- <translation type="unfinished">Nếu bạn đã chá»n giá»›i hạn block chain lÆ°u trữ (pruning),dữ liệu lịch sá»­ vẫn phải được tải xuống và xá»­ lý, nhÆ°ng sẽ bị xóa sau đó để giữ cho việc sá»­ dụng Ä‘Ä©a của bạn ở mức usage thấp.</translation>
+ <translation type="unfinished">Äảo ngược lại thiết lập này yêu cầu tại lại toàn bá»™ chuá»—i khối. Tải vá» toàn bá»™ chuá»—i khối trÆ°á»›c và loại nó sau đó sẽ nhanh hÆ¡n. Vô hiệu hóa má»™t số tính năng nâng cao.</translation>
</message>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
<message>
- <source>Use the default data directory</source>
- <translation type="unfinished">Sử dụng default danh mục đa ta</translation>
+ <source>About %1</source>
+ <translation type="unfinished">Vá» %1</translation>
</message>
<message>
- <source>Use a custom data directory:</source>
- <translation type="unfinished">Sử dụng custom danh mục data:</translation>
+ <source>Command-line options</source>
+ <translation type="unfinished">Tùy chá»n dòng lệnh</translation>
</message>
</context>
<context>
- <name>HelpMessageDialog</name>
- <message>
- <source>version</source>
- <translation type="unfinished">phiên bản</translation>
- </message>
- </context>
-<context>
<name>ShutdownWindow</name>
<message>
- <source>Do not shut down the computer until this window disappears.</source>
- <translation type="unfinished">Äừng tắt máy tính đến khi cá»­a sổ này đóng.</translation>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1 đang tắt…</translation>
</message>
-</context>
+ </context>
<context>
<name>ModalOverlay</name>
<message>
- <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
- <translation type="unfinished">Giao dịch gần đây có thể chưa được hiển thị, và vì vậy số dư wallet của bạn có thể không dúng. Thông tin này sẽ được làm đúng khi wallet hoàn thành đồng bộ với bitcoin network, như chi tiết bên dưới.</translation>
+ <source>Unknown…</source>
+ <translation type="unfinished">Không xác định…</translation>
</message>
<message>
- <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
- <translation type="unfinished">Cố gắng spend các bitcoins bị ảnh hưởng bởi các giao dịch chưa được hiển thị sẽ không được chấp nhận bởi mạng.</translation>
+ <source>calculating…</source>
+ <translation type="unfinished">đang tính toán…</translation>
</message>
<message>
- <source>Number of blocks left</source>
- <translation type="unfinished">Số của blocks còn lại</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation type="unfinished">Thá»i gian block cuối cùng</translation>
- </message>
- <message>
- <source>Progress</source>
- <translation type="unfinished">Tiến độ</translation>
- </message>
- <message>
- <source>Progress increase per hour</source>
- <translation type="unfinished">Tiến Ä‘á»™ tăng má»—i giá»</translation>
- </message>
- <message>
- <source>Estimated time left until synced</source>
- <translation type="unfinished">Ước tính thá»i gian còn lại đến khi đồng bá»™</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation type="unfinished">Ẩn</translation>
- </message>
- <message>
- <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
- <translation type="unfinished">%1 đang được đồng bộ. Header và block sẽ được download từ các nốt lân cận và thẩm định tới khi đạt đỉnh của blockchain.</translation>
+ <source>Unknown. Syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">Không xác định. Äồng bá»™ hóa tiêu Ä‘á» (%1, %2%)…</translation>
</message>
</context>
<context>
<name>OpenURIDialog</name>
<message>
- <source>Open bitcoin URI</source>
- <translation type="unfinished">Mở bitcoin URI</translation>
- </message>
- <message>
<source>Paste address from clipboard</source>
<extracomment>Tooltip text for button that allows you to paste an address that is in your clipboard.</extracomment>
- <translation type="unfinished">Paste address từ clipboard</translation>
+ <translation type="unfinished">Dán địa chỉ từ khay nhớ tạm</translation>
</message>
</context>
<context>
<name>OptionsDialog</name>
<message>
- <source>Options</source>
- <translation type="unfinished">Tùy chỉnh</translation>
- </message>
- <message>
- <source>&amp;Main</source>
- <translation type="unfinished">&amp;Chính</translation>
- </message>
- <message>
<source>Automatically start %1 after logging in to the system.</source>
- <translation type="unfinished">Tự động bắt đầu %1 sau khi đăng nhập vào system.</translation>
+ <translation type="unfinished">Tự động bắt đầu %1 sau khi đăng nhập vào hệ thống.</translation>
</message>
<message>
<source>&amp;Start %1 on system login</source>
- <translation type="unfinished">&amp;Bắt đầu %1 trên đăng nhập system</translation>
+ <translation type="unfinished">&amp;Bắt đầu %1 trên đăng nhập hệ thống</translation>
</message>
<message>
- <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
- <translation type="unfinished">Hiển thị nếu cung cấp default SOCKS5 proxy is used to reach peers via this network type.</translation>
+ <source>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>
+ <translation type="unfinished">Cho phép cắt bớt làm giảm đáng kể không gian đĩa cần thiết để lưu trữ các giao dịch. Tất cả các khối vẫn được xác nhận đầy đủ. Hoàn nguyên cài đặt này yêu cầu tải xuống lại toàn bộ chuỗi khối.</translation>
</message>
<message>
- <source>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>
- <translation type="unfinished">Minimize thay vì thoát khá»i ứng dụng khi cá»­a sổ đóng lại. Khi bật tùy chá»n này, ứng dụng sẽ chỉ được đóng sau khi chá»n Exit trong menu.</translation>
+ <source>Size of &amp;database cache</source>
+ <translation type="unfinished">Kích thước bộ nhớ cache của &amp;cơ sở dữ liệu</translation>
</message>
<message>
- <source>Open the %1 configuration file from the working directory.</source>
- <translation type="unfinished">Mở %1 configuration file từ danh mục làm việc working directory.</translation>
+ <source>Number of script &amp;verification threads</source>
+ <translation type="unfinished">Số lượng tập lệnh và chuỗi &amp;xác minh</translation>
</message>
<message>
- <source>Open Configuration File</source>
- <translation type="unfinished">Mở File cấu hình</translation>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation type="unfinished">Äịa chỉ IP của proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</translation>
</message>
<message>
- <source>Reset all client options to default.</source>
- <translation type="unfinished">Reset tất cả client options to default.</translation>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">Các tùy chá»n trong há»™p thoại này bị ghi đè bởi dòng lệnh</translation>
</message>
<message>
- <source>&amp;Reset Options</source>
- <translation type="unfinished">&amp;Reset Tùy chá»n</translation>
- </message>
- <message>
- <source>Prune &amp;block storage to</source>
- <translation type="unfinished">Cắt tỉa và lưu trữ khối tới</translation>
- </message>
- <message>
- <source>Reverting this setting requires re-downloading the entire blockchain.</source>
- <translation type="unfinished">Hoàn nguyên cài đặt này yêu cầu tải xuống lại toàn bộ blockchain.</translation>
- </message>
- <message>
- <source>Accept connections from outside.</source>
- <translation type="unfinished">Chấp nhận kết nối từ bên ngoài</translation>
- </message>
- <message>
- <source>Allow incomin&amp;g connections</source>
- <translation type="unfinished">Chấp nhận kết nối đang tới</translation>
- </message>
- <message>
- <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation type="unfinished">Kết nối đến Bitcoin network qua một SOCKS5 proxy.</translation>
- </message>
- <message>
- <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
- <translation type="unfinished">&amp;Connect qua SOCKS5 proxy (default proxy):</translation>
- </message>
- <message>
- <source>Used for reaching peers via:</source>
- <translation type="unfinished">Sử dụng reaching peers via:</translation>
- </message>
- <message>
- <source>Show only a tray icon after minimizing the window.</source>
- <translation type="unfinished">Hiển thị chỉ thẻ icon sau khi thu nhỠcửa sổ.</translation>
- </message>
- <message>
- <source>&amp;Minimize to the tray instead of the taskbar</source>
- <translation type="unfinished">&amp;Minimize đến thẻ thay vì taskbar</translation>
- </message>
- <message>
- <source>User Interface &amp;language:</source>
- <translation type="unfinished">Giao diện ngÆ°á»i dùng &amp;language:</translation>
- </message>
- <message>
- <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
- <translation type="unfinished">Giao diện ngôn ngữ ngÆ°á»i dùng có thể được thiết lập tại đây. Tùy chá»n này sẽ có hiệu lá»±c sau khi khởi Ä‘á»™ng lại %1.</translation>
+ <source>Reset all client options to default.</source>
+ <translation type="unfinished">Äặt lại tất cả các tùy chá»n máy khách vá» mặc định.</translation>
</message>
<message>
- <source>&amp;Unit to show amounts in:</source>
- <translation type="unfinished">&amp;Unit để hiện số lượng tại đây:</translation>
+ <source>&amp;Network</source>
+ <translation type="unfinished">&amp;Mạng</translation>
</message>
<message>
- <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
- <translation type="unfinished">Chá»n default Ä‘Æ¡n vị phân chia để hiện giao diện và Ä‘ang gá»­i coins.</translation>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">Kích thÆ°á»›c bá»™ đệm cÆ¡ sở dữ liệu tối Ä‘a. Bá»™ nhá»› đệm lá»›n hÆ¡n có thể góp phần đồng bá»™ hóa nhanh hÆ¡n, sau đó lợi ích ít rõ rệt hÆ¡n đối vá»›i hầu hết các trÆ°á»ng hợp sá»­ dụng. Giảm kích thÆ°á»›c bá»™ nhá»› cache sẽ làm giảm mức sá»­ dụng bá»™ nhá»›. Bá»™ nhá»› mempool không sá»­ dụng được chia sẻ cho bá»™ nhá»› cache này.</translation>
</message>
<message>
- <source>Whether to show coin control features or not.</source>
- <translation type="unfinished">Cho hiển thị tính năng coin control hoặc không.</translation>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Äặt số lượng chuá»—i xác minh tập lệnh. Giá trị âm tÆ°Æ¡ng ứng vá»›i số lõi bạn muốn để lại miá»…n phí cho hệ thống.</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
- <translation type="unfinished">Kết nối với mạng Bitcoin thông qua proxy SOCKS5 riêng cho các dịch vụ Tor</translation>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">Äiá»u này cho phép bạn hoặc công cụ của bên thứ ba giao tiếp vá»›i nút thông qua các lệnh dòng lệnh và JSON-RPC.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
- <translation type="unfinished">Sử dụng proxy SOCKS&amp;5 riêng biệt để tiếp cận các đối tác ngang hàng thông qua các dịch vụ Tor Onion.</translation>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">Bật máy chủ R&amp;PC</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">Các tùy chá»n được đặt trong há»™p thoại này bị ghi đè bởi dòng lệnh hoặc trong tệp cấu hình:</translation>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Có đặt trừ phí khá»i số tiá»n làm mặc định hay không.</translation>
</message>
<message>
- <source>&amp;Cancel</source>
- <translation type="unfinished">&amp;Hủy</translation>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">Trừ &amp;phí khá»i số tiá»n theo mặc định</translation>
</message>
<message>
- <source>none</source>
- <translation type="unfinished">không có gì</translation>
+ <source>Expert</source>
+ <translation type="unfinished">Chuyên gia</translation>
</message>
<message>
- <source>Confirm options reset</source>
- <translation type="unfinished">Confirm tùy chá»n reset</translation>
+ <source>Enable coin &amp;control features</source>
+ <translation type="unfinished">Bật tính năng &amp;kiểm soát và tiá»n xu</translation>
</message>
<message>
- <source>Client restart required to activate changes.</source>
- <translation type="unfinished">Client yêu cầu khởi động lại để thay đổi có hiệu lực.</translation>
+ <source>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>
+ <translation type="unfinished">Nếu bạn vô hiệu hóa chi tiêu của thay đổi chÆ°a được xác nhận, thay đổi từ má»™t giao dịch sẽ không thể được sá»­ dụng cho đến khi giao dịch đó có ít nhất má»™t xác nhận. Äiá»u này cÅ©ng ảnh hưởng đến cách tính số dÆ° của bạn.</translation>
</message>
<message>
- <source>Client will be shut down. Do you want to proceed?</source>
- <translation type="unfinished">Client sẽ đóng lại. Tiếp tục chứ?</translation>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation type="unfinished">&amp;Chi tiêu thay đổi chưa được xác nhận</translation>
</message>
<message>
- <source>Configuration options</source>
- <extracomment>Window title text of pop-up box that allows opening up of configuration file.</extracomment>
- <translation type="unfinished">Tùy chá»n cấu hình</translation>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">Bật Ä‘iá»u khiển &amp;PSBT</translation>
</message>
<message>
- <source>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>
- <extracomment>Explanatory text about the priority order of instructions considered by client. The order from high to low being: command-line, configuration file, GUI settings.</extracomment>
- <translation type="unfinished">File cấu hình được sá»­ dụng để chỉ định các tùy chá»n nâng cao của ngÆ°á»i dùng mà ghi đè GUI settings. Ngoài ra, bất kỳ tùy chá»n dòng lệnh sẽ ghi đè lên tập tin cấu hình này.</translation>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">Có hiển thị các Ä‘iá»u khiển PSBT hay không.</translation>
</message>
<message>
- <source>Cancel</source>
- <translation type="unfinished">Hủy</translation>
+ <source>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>
+ <translation type="unfinished">URL của bên thứ ba (ví dụ: trình khám phá khối) xuất hiện trong tab giao dịch dÆ°á»›i dạng các mục menu ngữ cảnh. %s trong URL được thay thế bằng mã băm giao dịch. Nhiá»u URL được phân tách bằng thanh dá»c |. </translation>
</message>
<message>
- <source>Error</source>
- <translation type="unfinished">Lá»—i</translation>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">&amp;URL giao dịch của bên thứ ba</translation>
</message>
<message>
- <source>The configuration file could not be opened.</source>
- <translation type="unfinished">Không thẻ mở tệp cấu hình.</translation>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">Äược biên dịch mà không có há»— trợ ký bên ngoài (bắt buá»™c đối vá»›i ký bên ngoài)</translation>
</message>
<message>
- <source>This change would require a client restart.</source>
- <translation type="unfinished">Việc change này sẽ cần một client restart.</translation>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">Các thiết lập hiện tại sẽ được sao lưu tại"%1".</translation>
</message>
<message>
- <source>The supplied proxy address is invalid.</source>
- <translation type="unfinished">Cung cấp proxy address thì invalid.</translation>
+ <source>Continue</source>
+ <translation type="unfinished">Tiếp tục</translation>
</message>
-</context>
+ </context>
<context>
- <name>OverviewPage</name>
+ <name>OptionsModel</name>
<message>
- <source>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>
- <translation type="unfinished">Thông tin được hiển thị có thể đã lá»—i thá»i. Cái wallet tá»± Ä‘á»™ng đồng bá»™ vá»›i Bitcoin network sau má»™t connection được thiết lập, nhÆ°ng quá trình này vẫn chÆ°a completed yet.</translation>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">Không thể Ä‘á»c thiết lập "%1", %2.</translation>
</message>
- <message>
- <source>Watch-only:</source>
- <translation type="unfinished">Chỉ-xem:</translation>
- </message>
- <message>
- <source>Available:</source>
- <translation type="unfinished">Có hiệu lực:</translation>
- </message>
- <message>
- <source>Your current spendable balance</source>
- <translation type="unfinished">Số dư khả dụng:</translation>
- </message>
- <message>
- <source>Pending:</source>
- <translation type="unfinished">Äang xá»­ lý:</translation>
- </message>
- <message>
- <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
- <translation type="unfinished">Tất cả giao dịch vẫn chưa được confirmed, và chưa tính vào số dư có thể chi tiêu</translation>
- </message>
- <message>
- <source>Immature:</source>
- <translation type="unfinished">Chưa hoàn thiện:</translation>
- </message>
- <message>
- <source>Mined balance that has not yet matured</source>
- <translation type="unfinished">Mined balance chưa matured hẳn</translation>
- </message>
- <message>
- <source>Balances</source>
- <translation type="unfinished">Số dư</translation>
- </message>
- <message>
- <source>Total:</source>
- <translation type="unfinished">Tổng cộng:</translation>
- </message>
- <message>
- <source>Your current total balance</source>
- <translation type="unfinished">Tổng số dư hiện tại</translation>
- </message>
- <message>
- <source>Your current balance in watch-only addresses</source>
- <translation type="unfinished">Số dư hiện tại trong địa chỉ watch-only</translation>
- </message>
- <message>
- <source>Spendable:</source>
- <translation type="unfinished">Có thể sử dụng</translation>
- </message>
- <message>
- <source>Recent transactions</source>
- <translation type="unfinished">Giao dịch gần đây</translation>
- </message>
- <message>
- <source>Unconfirmed transactions to watch-only addresses</source>
- <translation type="unfinished">Giao dịch chưa được xác nhận đến watch-only addresses</translation>
- </message>
- <message>
- <source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation type="unfinished">Mined số dư trong watch-only address chưa matured hẳn</translation>
- </message>
- <message>
- <source>Current total balance in watch-only addresses</source>
- <translation type="unfinished">Tổng số dư hiện tại trong watch-only addresses</translation>
- </message>
- </context>
+</context>
<context>
<name>PSBTOperationsDialog</name>
<message>
- <source>Dialog</source>
- <translation type="unfinished">Bảng thoại</translation>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">Không thể ký đầu vào khi ví bị khóa.</translation>
</message>
<message>
- <source>Sign Tx</source>
- <translation type="unfinished">Äăng ký Tx</translation>
- </message>
- <message>
- <source>Broadcast Tx</source>
- <translation type="unfinished">Truyá»n phát Tx</translation>
- </message>
- <message>
- <source>Copy to Clipboard</source>
- <translation type="unfinished">Lưu vào bảng tạm</translation>
- </message>
- <message>
- <source>Close</source>
- <translation type="unfinished">Äóng</translation>
- </message>
- <message>
- <source>Failed to load transaction: %1</source>
- <translation type="unfinished">Tải giao dịch thất bại: %1</translation>
- </message>
- <message>
- <source>Failed to sign transaction: %1</source>
- <translation type="unfinished">Äăng ký giao dịch thất bại :%1</translation>
- </message>
- <message>
- <source>Could not sign any more inputs.</source>
- <translation type="unfinished">Không thể thêm bất cứ nguồn vào nào.</translation>
- </message>
- <message>
- <source>Signed %1 inputs, but more signatures are still required.</source>
- <translation type="unfinished">Nguồn %1 đã nạp, nhưng vẫn cần thêm các nguồn khác.</translation>
- </message>
- <message>
- <source>Unknown error processing transaction.</source>
- <translation type="unfinished">Lỗi không xác định xử lý giao dịch</translation>
- </message>
- <message>
- <source>Transaction broadcast successfully! Transaction ID: %1</source>
- <translation type="unfinished">Giao dịch dã được truyá»n thành công: Mã giao dịch: %1</translation>
- </message>
- <message>
- <source>Transaction broadcast failed: %1</source>
- <translation type="unfinished">Giao dịch truyá»n phát không thành công: %1</translation>
- </message>
- <message>
- <source>PSBT copied to clipboard.</source>
- <translation type="unfinished">Dữ liệu PSBT được sao chép vào bộ nhớ tạm.</translation>
- </message>
- <message>
- <source>Save Transaction Data</source>
- <translation type="unfinished">Lưu trữ giao dịch</translation>
- </message>
- <message>
- <source>PSBT saved to disk.</source>
- <translation type="unfinished">Dữ liệu PSBT được lưu vào ổ đĩa.</translation>
- </message>
- <message>
- <source> * Sends %1 to %2</source>
- <translation type="unfinished">*Gá»­i %1 tá»›i %2</translation>
- </message>
- <message>
- <source>Unable to calculate transaction fee or total transaction amount.</source>
- <translation type="unfinished">Không thể tính phí giao dịch hoặc tổng số tiá»n giao dịch.</translation>
- </message>
- <message>
- <source>Pays transaction fee: </source>
- <translation type="unfinished">Trả phí giao dịch</translation>
- </message>
- <message>
- <source>Total Amount</source>
- <translation type="unfinished">Tổng số</translation>
- </message>
- <message>
- <source>or</source>
- <translation type="unfinished">hoặc</translation>
- </message>
- <message>
- <source>Transaction is missing some information about inputs.</source>
- <translation type="unfinished">Giao dịch thiếu một số thông tin vỠđầu vào.</translation>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation type="unfinished">Giao dịch có %1 đầu vào chưa được ký.</translation>
</message>
<message>
<source>Transaction still needs signature(s).</source>
- <translation type="unfinished">Giao dịch cần chữ ký</translation>
- </message>
- <message>
- <source>(But this wallet cannot sign transactions.)</source>
- <translation type="unfinished">(Nhưng ví này không thể đăng ký giao dịch.)</translation>
+ <translation type="unfinished">Giao dịch vẫn cần (các) chữ ký.</translation>
</message>
<message>
- <source>(But this wallet does not have the right keys.)</source>
- <translation type="unfinished">(Nhưng ví này không có chìa khóa phù hợp.)</translation>
- </message>
- <message>
- <source>Transaction is fully signed and ready for broadcast.</source>
- <translation type="unfinished">Giao dịch đã được đăng ký và chuẩn bị để phát lên</translation>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(Nhưng không có ví nào được tải.)</translation>
</message>
</context>
<context>
- <name>PaymentServer</name>
- <message>
- <source>Cannot start bitcoin: click-to-pay handler</source>
- <translation type="unfinished">Không thể khởi tạo bitcoin: click-to-pay handler</translation>
- </message>
- <message>
- <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
- <translation type="unfinished">'bitcoin://' không khả dụng URI. Dùng thay vì 'bitcoin:' .</translation>
- </message>
- <message>
- <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation type="unfinished">URI không thể phân tích cú pháp! Äây có thể gây nên bởi invalid Bitcoin address hoặc URI không đúng định dạng tham số.</translation>
- </message>
- <message>
- <source>Payment request file handling</source>
- <translation type="unfinished">Payment request file đang xử lý</translation>
- </message>
-</context>
-<context>
<name>PeerTableModel</name>
<message>
- <source>User Agent</source>
- <extracomment>Title of Peers Table column which contains the peer's User Agent string.</extracomment>
- <translation type="unfinished">User Äặc Vụ</translation>
- </message>
- <message>
- <source>Sent</source>
- <extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
- <translation type="unfinished">Gá»­i</translation>
- </message>
- <message>
- <source>Received</source>
- <extracomment>Title of Peers Table column which indicates the total amount of network information we have received from the peer.</extracomment>
- <translation type="unfinished">Nhận</translation>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">Tuổi</translation>
</message>
<message>
<source>Address</source>
<extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
<translation type="unfinished">Äịa chỉ</translation>
</message>
- <message>
- <source>Network</source>
- <extracomment>Title of Peers Table column which states the network the peer connected through.</extracomment>
- <translation type="unfinished">Mạng</translation>
- </message>
- </context>
-<context>
- <name>QRImageWidget</name>
- <message>
- <source>&amp;Copy Image</source>
- <translation type="unfinished">&amp;Sao chép ảnh</translation>
- </message>
- <message>
- <source>Resulting URI too long, try to reduce the text for label / message.</source>
- <translation type="unfinished">Äang tính toán URI quá dài, cố gắng giảm text cho label / message.</translation>
- </message>
- <message>
- <source>Error encoding URI into QR Code.</source>
- <translation type="unfinished">Error đang mã hóa URI đến QR Code.</translation>
- </message>
- <message>
- <source>QR code support not available.</source>
- <translation type="unfinished">Sự hổ trợ mã QR không sẵn có</translation>
- </message>
- <message>
- <source>Save QR Code</source>
- <translation type="unfinished">LÆ°u QR Code</translation>
- </message>
</context>
<context>
<name>RPCConsole</name>
<message>
- <source>&amp;Information</source>
- <translation type="unfinished">&amp;Thông tin</translation>
- </message>
- <message>
- <source>General</source>
- <translation type="unfinished">Tổng thể</translation>
- </message>
- <message>
- <source>To specify a non-default location of the data directory use the '%1' option.</source>
- <translation type="unfinished">Äể chỉ ra má»™t nÆ¡i không mặt định của thÆ° mục dữ liệu hãy dùng tùy chá»n '%1'</translation>
- </message>
- <message>
- <source>Blocksdir</source>
- <translation type="unfinished">Thư mục chứa các khối Blocksdir</translation>
- </message>
- <message>
- <source>To specify a non-default location of the blocks directory use the '%1' option.</source>
- <translation type="unfinished">Äể chỉ ra má»™t nÆ¡i không mặt định của thÆ° mục các khối hãy dùng tùy chá»n '%1'</translation>
- </message>
- <message>
- <source>Startup time</source>
- <translation type="unfinished">Startup lúc</translation>
- </message>
- <message>
- <source>Network</source>
- <translation type="unfinished">Mạng</translation>
- </message>
- <message>
- <source>Name</source>
- <translation type="unfinished">Tên</translation>
- </message>
- <message>
- <source>Number of connections</source>
- <translation type="unfinished">Số lượng connections</translation>
- </message>
- <message>
- <source>Memory Pool</source>
- <translation type="unfinished">Pool Bá»™ Nhá»›</translation>
- </message>
- <message>
- <source>Current number of transactions</source>
- <translation type="unfinished">Số giao dịch hiện tại</translation>
- </message>
- <message>
- <source>Memory usage</source>
- <translation type="unfinished">Bá»™ nhá»› usage</translation>
- </message>
- <message>
- <source>Wallet: </source>
- <translation type="unfinished">Ví :</translation>
- </message>
- <message>
- <source>(none)</source>
- <translation type="unfinished">(không)</translation>
- </message>
- <message>
- <source>Received</source>
- <translation type="unfinished">Nhận</translation>
- </message>
- <message>
- <source>Sent</source>
- <translation type="unfinished">Gá»­i</translation>
- </message>
- <message>
- <source>Banned peers</source>
- <translation type="unfinished">Bị khóa peers</translation>
- </message>
- <message>
- <source>Select a peer to view detailed information.</source>
- <translation type="unfinished">Chá»n má»™t peer để xem thông tin chi tiết.</translation>
+ <source>Last Transaction</source>
+ <translation type="unfinished">Giao dịch cuối cùng</translation>
</message>
<message>
- <source>Version</source>
- <translation type="unfinished">Phiên bản</translation>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Cho dù chúng tôi chuyển tiếp địa chỉ đến đồng đẳng này.</translation>
</message>
<message>
- <source>Starting Block</source>
- <translation type="unfinished">Block Bắt Äầu</translation>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">Chuyển tiếp địa chỉ</translation>
</message>
<message>
- <source>Synced Headers</source>
- <translation type="unfinished">Headers đã được đồng bộ</translation>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Tổng số các địa chỉ đã được xá»­ lý thành công nhận được từ ngÆ°á»i này (ngoại trừ các địa chỉ sụt giảm do giá»›i hạn tốc Ä‘á»™) </translation>
</message>
<message>
- <source>Synced Blocks</source>
- <translation type="unfinished">Blocks đã được đồng bộ</translation>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Tổng số các địa chỉ nhận được từ ngÆ°á»i ngày đã bị sụt giảm (không được xá»­ lý thành công) do giá»›i hạn vá» tốc Ä‘á»™.</translation>
</message>
<message>
- <source>The mapped Autonomous System used for diversifying peer selection.</source>
- <translation type="unfinished">Hệ thống tá»± Ä‘á»™ng ánh xạ được sá»­ dụng để Ä‘a dạng hóa lá»±a chá»n ngang hàng.</translation>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">Các địa chỉ đã được xử lý</translation>
</message>
<message>
- <source>Mapped AS</source>
- <translation type="unfinished">AS đã được map</translation>
- </message>
- <message>
- <source>User Agent</source>
- <translation type="unfinished">User Äặc Vụ</translation>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">Tỷ lệ địa chỉ có giới hạn</translation>
</message>
<message>
<source>Node window</source>
<translation type="unfinished">Cửa sổ node</translation>
</message>
<message>
- <source>Current block height</source>
- <translation type="unfinished">Kích thước khối hiện tại</translation>
- </message>
- <message>
- <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
- <translation type="unfinished">Mở cái %1 debug log file từ danh mục dữ liệu hiện tại. Äiá»u này cần vài giây cho large log files.</translation>
- </message>
- <message>
- <source>Decrease font size</source>
- <translation type="unfinished">Giảm font size</translation>
- </message>
- <message>
- <source>Increase font size</source>
- <translation type="unfinished">Tăng font size</translation>
- </message>
- <message>
- <source>Permissions</source>
- <translation type="unfinished">Cho phép</translation>
- </message>
- <message>
- <source>Services</source>
- <translation type="unfinished">Dịch vụ</translation>
- </message>
- <message>
- <source>Connection Time</source>
- <translation type="unfinished">Connection Thá»i Gian</translation>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">&amp;Sao chép IP/Netmask</translation>
</message>
- <message>
- <source>Last Send</source>
- <translation type="unfinished">Gửi Sau Cùng</translation>
- </message>
- <message>
- <source>Last Receive</source>
- <translation type="unfinished">Nhận Sau Cùng</translation>
- </message>
- <message>
- <source>The duration of a currently outstanding ping.</source>
- <translation type="unfinished">Thá»i hạn của má»™t ping hiện Ä‘ang nổi trá»™i.</translation>
- </message>
- <message>
- <source>Ping Wait</source>
- <translation type="unfinished">Ping Chá»</translation>
- </message>
- <message>
- <source>Min Ping</source>
- <translation type="unfinished">Ping NhỠNhất</translation>
- </message>
- <message>
- <source>Time Offset</source>
- <translation type="unfinished">Thá»i gian Offset</translation>
- </message>
- <message>
- <source>Last block time</source>
- <translation type="unfinished">Thá»i gian block cuối cùng</translation>
- </message>
- <message>
- <source>&amp;Console</source>
- <translation type="unfinished">&amp;BangDieuKhien</translation>
- </message>
- <message>
- <source>Debug log file</source>
- <translation type="unfinished">Debug file log</translation>
- </message>
- <message>
- <source>Clear console</source>
- <translation type="unfinished">Xóa console</translation>
- </message>
- <message>
- <source>Executing command without any wallet</source>
- <translation type="unfinished">Äang chạy lệnh khi không có ví nào</translation>
- </message>
- <message>
- <source>Executing command using "%1" wallet</source>
- <translation type="unfinished">Chạy lệnh bằng ví "%1"</translation>
- </message>
- <message>
- <source>Unknown</source>
- <translation type="unfinished">Không biết</translation>
- </message>
-</context>
-<context>
- <name>ReceiveCoinsDialog</name>
- <message>
- <source>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>
- <translation type="unfinished">Má»™t optional lá»i nhắn để đính kèm đến payment request, cái mà sẽ được hiển thị khi mà request Ä‘ang mở. LÆ°u ý: Tin nhắn này sẽ không được gá»­i vá»›i payment over the Bitcoin network.</translation>
- </message>
- <message>
- <source>An optional label to associate with the new receiving address.</source>
- <translation type="unfinished">Một optional label để liên kết với address đang nhận mới.</translation>
- </message>
- <message>
- <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
- <translation type="unfinished">Sử dụng form cho request thanh toán. Tất cả chỗ trống là &lt;b&gt;optional&lt;/b&gt;.</translation>
- </message>
- <message>
- <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation type="unfinished">Má»™t optional giá trị để request. Äể lại đây khoảng trống hoặc zero để không request má»™t giá trị xác định.</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Má»™t nhãn tùy chá»n để liên kết vá»›i địa chỉ nhận má»›i (được bạn sá»­ dụng để xác định hóa Ä‘Æ¡n). Nó cÅ©ng được đính kèm vá»›i yêu cầu thanh toán.</translation>
- </message>
- <message>
- <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
- <translation type="unfinished">Má»™t thông báo tùy chá»n được đính kèm vá»›i yêu cầu thanh toán và có thể được hiển thị cho ngÆ°á»i gá»­i.</translation>
- </message>
- <message>
- <source>&amp;Create new receiving address</source>
- <translation type="unfinished">&amp;Tạo địa chỉ nhận mới</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation type="unfinished">Xóa hết các khoảng trống của form.</translation>
- </message>
- <message>
- <source>Clear</source>
- <translation type="unfinished">Xóa</translation>
- </message>
- <message>
- <source>Requested payments history</source>
- <translation type="unfinished">Yêu cầu lịch sử giao dịch</translation>
- </message>
- <message>
- <source>Show the selected request (does the same as double clicking an entry)</source>
- <translation type="unfinished">Hiển thị request đã chá»n (does the same as double clicking an entry)</translation>
- </message>
- <message>
- <source>Show</source>
- <translation type="unfinished">Hiển thị</translation>
- </message>
- <message>
- <source>Remove the selected entries from the list</source>
- <translation type="unfinished">Xóa bá» mục Ä‘ang chá»n từ danh sách</translation>
- </message>
- <message>
- <source>Remove</source>
- <translation type="unfinished">Gỡ bá»</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation type="unfinished">Sao chép &amp;URI</translation>
- </message>
- <message>
- <source>Could not unlock wallet.</source>
- <translation type="unfinished">Không thể unlock wallet.</translation>
- </message>
- <message>
- <source>Could not generate new %1 address</source>
- <translation type="unfinished">Không thể tạo ra %1 địa chỉ mới</translation>
- </message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Address:</source>
- <translation type="unfinished">Äịa chỉ</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation type="unfinished">Số lượng:</translation>
- </message>
- <message>
- <source>Label:</source>
- <translation type="unfinished">Nhãn</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation type="unfinished">Tin nhắn:</translation>
- </message>
- <message>
- <source>Wallet:</source>
- <translation type="unfinished">Ví tiá»n</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation type="unfinished">Sao chép &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation type="unfinished">Sao chép địa chỉ</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation type="unfinished">Payment thông tin</translation>
- </message>
- <message>
- <source>Request payment to %1</source>
- <translation type="unfinished">Request payment đến %1</translation>
- </message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
- <source>Date</source>
- <translation type="unfinished">Ngày</translation>
- </message>
- <message>
<source>Label</source>
<translation type="unfinished">Nhãn</translation>
</message>
<message>
- <source>Message</source>
- <translation type="unfinished">Tin nhắn</translation>
- </message>
- <message>
<source>(no label)</source>
- <translation type="unfinished">(không nhãn)</translation>
- </message>
- <message>
- <source>(no message)</source>
- <translation type="unfinished">(no tin nhắn)</translation>
+ <translation type="unfinished">(không có nhãn)</translation>
</message>
- <message>
- <source>(no amount requested)</source>
- <translation type="unfinished">(không amount yêu cầu)</translation>
- </message>
- <message>
- <source>Requested</source>
- <translation type="unfinished">Äã yêu cầu</translation>
- </message>
-</context>
+ </context>
<context>
<name>SendCoinsDialog</name>
<message>
- <source>Send Coins</source>
- <translation type="unfinished">Gá»­i Coins</translation>
- </message>
- <message>
- <source>Coin Control Features</source>
- <translation type="unfinished">Coin Control Tính-năng</translation>
- </message>
- <message>
- <source>automatically selected</source>
- <translation type="unfinished">được chá»n má»™t cách hoàn toàn tá»± Ä‘á»™ng</translation>
- </message>
- <message>
- <source>Insufficient funds!</source>
- <translation type="unfinished">Không đủ tiá»n kìa!</translation>
- </message>
- <message>
- <source>Quantity:</source>
- <translation type="unfinished">Số lượng:</translation>
- </message>
- <message>
- <source>Amount:</source>
- <translation type="unfinished">Số lượng:</translation>
- </message>
- <message>
- <source>Fee:</source>
- <translation type="unfinished">Phí:</translation>
- </message>
- <message>
- <source>After Fee:</source>
- <translation type="unfinished">Sau Phí:</translation>
- </message>
- <message>
- <source>Change:</source>
- <translation type="unfinished">Thay đổi:</translation>
- </message>
- <message>
- <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
- <translation type="unfinished">Nếu cái này được bật, nhưng việc change address thì trống hoặc invalid, change sẽ được gửi cho một address vừa được tạo mới.</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Sá»­ dụng fallbackfee có thể dẫn đến hết quả Ä‘ang gá»­i má»™t transaction mà nó sẽ mất hàng giá» hoặc ngày (hoặc chẳng bao giá») được confirm. Suy nghÄ© chá»n fee của bạn bình thÆ°á»ng hoặc chá» cho đến khi validated hoàn thành chain.</translation>
- </message>
- <message>
- <source>Warning: Fee estimation is currently not possible.</source>
- <translation type="unfinished">Warning: Fee ước tính hiện tại không khả thi.</translation>
- </message>
- <message>
- <source>per kilobyte</source>
- <translation type="unfinished">trên mỗi kilobyte</translation>
- </message>
- <message>
- <source>Hide</source>
- <translation type="unfinished">Ẩn</translation>
- </message>
- <message>
- <source>Recommended:</source>
- <translation type="unfinished">Khuyên dùng:</translation>
- </message>
- <message>
- <source>Send to multiple recipients at once</source>
- <translation type="unfinished">Gá»­i đến tập thể ngÆ°á»i nhận má»™t lần</translation>
- </message>
- <message>
- <source>Clear all fields of the form.</source>
- <translation type="unfinished">Xóa hết các khoảng trống của form.</translation>
- </message>
- <message>
- <source>Dust:</source>
- <translation type="unfinished">Rác:</translation>
- </message>
- <message>
- <source>Hide transaction fee settings</source>
- <translation type="unfinished">Ẩn cài đặt phí giao dịch</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Khi có khối lượng giao dịch ít hÆ¡n chổ trống trong các khối, các nhà đào má» cÅ©ng nhÆ° các nút chuyển tiếp có thể thá»±c thi chỉ vá»›i má»™t khoản phí tối thiểu. Chỉ trả khoản phí tối thiểu này là tốt, nhÆ°ng lÆ°u ý rằng Ä‘iá»u này có thể dẫn đến má»™t giao dịch không bao giá» xác nhận má»™t khi có nhu cầu giao dịch bitcoin nhiá»u hÆ¡n khả năng mạng có thể xá»­ lý.</translation>
- </message>
- <message>
- <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
- <translation type="unfinished">Má»™t khoản phí quá thấp có thể dẫn đến má»™t giao dịch không bao giá» xác nhận (Ä‘á»c chú giải công cụ)</translation>
- </message>
- <message>
- <source>Confirmation time target:</source>
- <translation type="unfinished">Thá»i gian xác nhận đối tượng:</translation>
- </message>
- <message>
- <source>Enable Replace-By-Fee</source>
- <translation type="unfinished">Kích hoạt Phí thay thế</translation>
- </message>
- <message>
- <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
- <translation type="unfinished">Vá»›i Phí thay thế (BIP-125), bạn có thể tăng phí giao dịch sau khi được gá»­i. Nếu không có Ä‘iá»u này, má»™t khoản phí cao hÆ¡n có thể được Ä‘á» xuất để bù đắp cho rủi ro chậm trá»… giao dịch tăng lên.</translation>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">Bạn có muốn tạo giao dịch này không?</translation>
</message>
<message>
- <source>Balance:</source>
- <translation type="unfinished">Số dư:</translation>
- </message>
- <message>
- <source>Confirm the send action</source>
- <translation type="unfinished">Confirm hành động gửi</translation>
- </message>
- <message>
- <source>Copy quantity</source>
- <translation type="unfinished">Sao chép số lượng</translation>
- </message>
- <message>
- <source>Copy amount</source>
- <translation type="unfinished">Sao chép số lượng</translation>
- </message>
- <message>
- <source>Copy fee</source>
- <translation type="unfinished">Sao chép phí</translation>
- </message>
- <message>
- <source>Copy after fee</source>
- <translation type="unfinished">Sao chép sau phí</translation>
- </message>
- <message>
- <source>Copy bytes</source>
- <translation type="unfinished">Sao chép bytes</translation>
- </message>
- <message>
- <source>Copy dust</source>
- <translation type="unfinished">Sao chép rác</translation>
- </message>
- <message>
- <source>Copy change</source>
- <translation type="unfinished">Sao chép thay đổi</translation>
- </message>
- <message>
- <source>Cr&amp;eate Unsigned</source>
- <translation type="unfinished">Cr&amp;eate không được ký</translation>
- </message>
- <message>
- <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation type="unfinished">Tạo Giao dịch Bitcoin được ký một phần (PSBT) để sử dụng với các dạng như: ví ngoại tuyến %1 hoặc ví phần cứng tương thích PSBT.</translation>
- </message>
- <message>
- <source> from wallet '%1'</source>
- <translation type="unfinished">từ ví '%1'</translation>
- </message>
- <message>
- <source>%1 to '%2'</source>
- <translation type="unfinished">%1 tá»›i '%2'</translation>
- </message>
- <message>
- <source>%1 to %2</source>
- <translation type="unfinished">%1 đến%2</translation>
- </message>
- <message>
- <source>Save Transaction Data</source>
- <translation type="unfinished">Lưu trữ giao dịch</translation>
- </message>
- <message>
- <source>PSBT saved</source>
- <translation type="unfinished">PSBT đã lưu</translation>
- </message>
- <message>
- <source>or</source>
- <translation type="unfinished">hoặc</translation>
- </message>
- <message>
- <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
- <translation type="unfinished">Bạn có thể tăng phí sau khi gửi( với tín hiệu Phí Thay Thế, BIP-125)</translation>
- </message>
- <message>
- <source>Please, review your transaction.</source>
- <extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
- <translation type="unfinished">Làm ơn xem xét đánh giá giao dịch của bạn.</translation>
- </message>
- <message>
- <source>Not signalling Replace-By-Fee, BIP-125.</source>
- <translation type="unfinished">Không có tín hiệu Phí Thay Thế, BIP-125.</translation>
- </message>
- <message>
- <source>Total Amount</source>
- <translation type="unfinished">Tổng số</translation>
- </message>
- <message>
- <source>Confirm send coins</source>
- <translation type="unfinished">Confirm gá»­i coins</translation>
- </message>
- <message>
- <source>Watch-only balance:</source>
- <translation type="unfinished">Số dư chỉ xem:</translation>
- </message>
- <message>
- <source>The recipient address is not valid. Please recheck.</source>
- <translation type="unfinished">Äịa chỉ ngÆ°á»i nhận address thì không valid. Kiểm tra lại Ä‘i.</translation>
- </message>
- <message>
- <source>The amount to pay must be larger than 0.</source>
- <translation type="unfinished">Giả trị để pay cần phải lớn hơn 0.</translation>
- </message>
- <message>
- <source>The amount exceeds your balance.</source>
- <translation type="unfinished">Số tiá»n vượt quá số dÆ° của bạn.</translation>
- </message>
- <message>
- <source>The total exceeds your balance when the %1 transaction fee is included.</source>
- <translation type="unfinished">Tổng số lớn hơn số dư của bạn khi %1 transaction fee được tính vào.</translation>
- </message>
- <message>
- <source>Duplicate address found: addresses should only be used once each.</source>
- <translation type="unfinished">Trùng address được tìm thấy: địa chỉ chỉ nên được dùng một lần.</translation>
- </message>
- <message>
- <source>Transaction creation failed!</source>
- <translation type="unfinished">Transaction khởi tạo thất bại!</translation>
- </message>
- <message>
- <source>A fee higher than %1 is considered an absurdly high fee.</source>
- <translation type="unfinished">Một fee lớn hơn %1 được coi là ngớ ngẩn cao fee.</translation>
- </message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">Payment request hết hạn.</translation>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Vui lòng xem lại giao dịch của bạn. Bạn có thể tạo và gửi giao dịch này hoặc tạo Giao dịch Bitcoin được ký một phần (PSBT), bạn có thể lưu hoặc sao chép và sau đó ký bằng, ví dụ: ví %1 ngoại tuyến hoặc ví phần cứng tương thích với PSBT.</translation>
</message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
@@ -2149,81 +1012,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
- <source>Warning: Unknown change address</source>
- <translation type="unfinished">Warning: Không biết change address</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">The address bạn đã chá»n dành cho change thì không phải part of this wallet. Bất kỳ hay tất cả funds in your wallet có thể được gá»­i đến address này. Bạn chắc chứ?</translation>
- </message>
- <message>
<source>(no label)</source>
- <translation type="unfinished">(không nhãn)</translation>
+ <translation type="unfinished">(không có nhãn)</translation>
</message>
</context>
<context>
<name>SendCoinsEntry</name>
<message>
- <source>Choose previously used address</source>
- <translation type="unfinished">Chá»n má»›i thì address</translation>
- </message>
- <message>
- <source>The Bitcoin address to send the payment to</source>
- <translation type="unfinished">The Bitcoin address để gửi the payment đến</translation>
- </message>
- <message>
<source>Paste address from clipboard</source>
- <translation type="unfinished">Paste address từ clipboard</translation>
- </message>
- <message>
- <source>Remove this entry</source>
- <translation type="unfinished">Xóa bỠentry này</translation>
- </message>
- <message>
- <source>The amount to send in the selected unit</source>
- <translation type="unfinished">Lượng tiá»n để gá»­i trong má»—i Ä‘Æ¡n vị đã chá»n</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">The fee sẽ được khấu trừ từ số tiá»n Ä‘ang gá»­i. NgÆ°á»i nhận sẽ receive ít bitcoins hÆ¡n bạn gõ vào khoảng trống. Nếu nhiá»u ngÆ°á»i gá»­i được chá»n, fee sẽ được chia Ä‘á»u.</translation>
- </message>
- <message>
- <source>S&amp;ubtract fee from amount</source>
- <translation type="unfinished">S&amp;ubtract fee từ amount</translation>
- </message>
- <message>
- <source>Use available balance</source>
- <translation type="unfinished">Sử dụng số dư sẵn có</translation>
- </message>
- <message>
- <source>Message:</source>
- <translation type="unfinished">Tin nhắn:</translation>
- </message>
- <message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">Äây là má»™t chÆ°a được chứng thá»±c payment request.</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">Äây là má»™t chÆ°a được chứng thá»±c payment request.</translation>
- </message>
- <message>
- <source>Enter a label for this address to add it to the list of used addresses</source>
- <translation type="unfinished">Nhập một label cho cái address này để thêm vào danh sách địa chỉ đã sử dụng</translation>
- </message>
- <message>
- <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
- <translation type="unfinished">Một tin nhắn được đính kèm với số bitcoin: URI mà sẽ được lưu giữ với transaction dành cho tài liệu tham khảo. Lưu ý: Tin nhắn này sẽ không được gửi thông qua Bitcoin network.</translation>
- </message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">Pay Äến:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">Bản ghi nhớ:</translation>
+ <translation type="unfinished">Dán địa chỉ từ khay nhớ tạm</translation>
</message>
-</context>
+ </context>
<context>
<name>SendConfirmationDialog</name>
<message>
@@ -2234,107 +1033,28 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>SignVerifyMessageDialog</name>
<message>
- <source>Signatures - Sign / Verify a Message</source>
- <translation type="unfinished">Chữ ký - Sign / Verify a Message</translation>
- </message>
- <message>
- <source>&amp;Sign Message</source>
- <translation type="unfinished">&amp;Sign Tin nhắn</translation>
- </message>
- <message>
- <source>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>
- <translation type="unfinished">Bạn có thể ký/đồng ý với địa chỉ chứng minh bạn có thể receive bitcoins đã gửi đến chúng. Cẩn thận không ký bất cứ không rõ hay random, như các cuộc tấn công lừa đảo có thể cố lừa bạn ký tên vào danh tính của bạn.. Chỉ ký các bản tuyên bố hoàn chỉnh mà bạn đồng ý.</translation>
- </message>
- <message>
- <source>The Bitcoin address to sign the message with</source>
- <translation type="unfinished">The Bitcoin address để ký với tin nhắn</translation>
- </message>
- <message>
- <source>Choose previously used address</source>
- <translation type="unfinished">Chá»n má»›i thì address</translation>
- </message>
- <message>
<source>Paste address from clipboard</source>
- <translation type="unfinished">Paste address từ clipboard</translation>
- </message>
- <message>
- <source>Enter the message you want to sign here</source>
- <translation type="unfinished">Nhập tin nhắn bạn muốn ký tại đây</translation>
- </message>
- <message>
- <source>Copy the current signature to the system clipboard</source>
- <translation type="unfinished">Copy hiện tại signature tới system clipboard</translation>
- </message>
- <message>
- <source>Sign the message to prove you own this Bitcoin address</source>
- <translation type="unfinished">Ký tin nhắn để chứng minh bạn sở hữu Bitcoin address này</translation>
- </message>
- <message>
- <source>Reset all sign message fields</source>
- <translation type="unfinished">Reset tất cả khoảng chữ ký nhắn</translation>
- </message>
- <message>
- <source>&amp;Verify Message</source>
- <translation type="unfinished">&amp;Verify Tin nhắn</translation>
- </message>
- <message>
- <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation type="unfinished">Nhập vào address ngÆ°á»i nhận, tin nhắn (chắc rằng bạn copy line breaks, khoảng trống, tabs, etc. chính xác) và signature bên dÆ°á»›i verify tin nhắn. Cẩn thận không Ä‘á»c nhiá»u hÆ¡n từ signature so vá»›i cái được ký trong bản thân tin nhắn, để tránh bị lừa bá»›i man-in-the-middle tấn công. LÆ°u ý rằng Ä‘iá»u này chỉ chứng nhận nhóm những ngÆ°á»i nhân vá»›i address, nó không thể chứng minh bên gá»­i có bất kỳ transaction!</translation>
- </message>
- <message>
- <source>The Bitcoin address the message was signed with</source>
- <translation type="unfinished">The Bitcoin address tin nhắn đã ký với</translation>
- </message>
- <message>
- <source>The signed message to verify</source>
- <translation type="unfinished">Tin nhắn đã được ký để xác nhận</translation>
- </message>
- <message>
- <source>The signature given when the message was signed</source>
- <translation type="unfinished">Chữ ký được cung cấp khi tin nhắn đã được ký</translation>
- </message>
- <message>
- <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation type="unfinished">Verify tin nhắn để chắc rằng nó đã được ký với xác định Bitcoin address</translation>
- </message>
- <message>
- <source>Reset all verify message fields</source>
- <translation type="unfinished">Reset tất cả verify khoảng trống nhắn</translation>
- </message>
- <message>
- <source>Click "Sign Message" to generate signature</source>
- <translation type="unfinished">Click "Sign Message" để generate signature</translation>
- </message>
- <message>
- <source>The entered address is invalid.</source>
- <translation type="unfinished">Äã nhập address thì invalid.</translation>
- </message>
- <message>
- <source>Please check the address and try again.</source>
- <translation type="unfinished">Vui lòng kiểm tra address và thử lại.</translation>
- </message>
- <message>
- <source>The entered address does not refer to a key.</source>
- <translation type="unfinished">Äã nhập address không refer to a key.</translation>
- </message>
- <message>
- <source>Wallet unlock was cancelled.</source>
- <translation type="unfinished">Wallet unlock đã được hủy.</translation>
- </message>
- <message>
- <source>No error</source>
- <translation type="unfinished">Không lỗi</translation>
+ <translation type="unfinished">Dán địa chỉ từ khay nhớ tạm</translation>
</message>
+ </context>
+<context>
+ <name>SplashScreen</name>
<message>
- <source>Private key for the entered address is not available.</source>
- <translation type="unfinished">Private key cho address đã nhập thì không có sẵn.</translation>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">nhấn q để tắt máy</translation>
</message>
- </context>
+</context>
<context>
<name>TransactionDesc</name>
<message>
- <source>Date</source>
- <translation type="unfinished">Ngày</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/xác nhận, ở trong bể bộ nhớ - memory pool</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/xác nhận, không ở trong bể bộ nhớ - memory pool</translation>
</message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
@@ -2342,88 +1062,28 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<numerusform />
</translation>
</message>
- <message>
- <source>Message</source>
- <translation type="unfinished">Tin nhắn</translation>
- </message>
- <message>
- <source>Transaction virtual size</source>
- <translation type="unfinished">Kích cỡ giao dịch ảo</translation>
- </message>
- <message>
- <source> (Certificate was not verified)</source>
- <translation type="unfinished">(Chứng chỉ chưa được thẩm định)</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation type="unfinished">Số lượng</translation>
- </message>
</context>
<context>
<name>TransactionTableModel</name>
<message>
- <source>Date</source>
- <translation type="unfinished">Ngày</translation>
- </message>
- <message>
<source>Label</source>
<translation type="unfinished">Nhãn</translation>
</message>
<message>
- <source>Conflicted</source>
- <translation type="unfinished">Xung Ä‘á»™t</translation>
- </message>
- <message>
<source>(no label)</source>
- <translation type="unfinished">(không nhãn)</translation>
+ <translation type="unfinished">(không có nhãn)</translation>
</message>
</context>
<context>
<name>TransactionView</name>
<message>
- <source>All</source>
- <translation type="unfinished">Tất cả</translation>
- </message>
- <message>
- <source>Today</source>
- <translation type="unfinished">Hôm nay</translation>
- </message>
- <message>
- <source>This week</source>
- <translation type="unfinished">Tuần này</translation>
- </message>
- <message>
- <source>This month</source>
- <translation type="unfinished">Tháng này</translation>
- </message>
- <message>
- <source>Last month</source>
- <translation type="unfinished">Tháng trước</translation>
- </message>
- <message>
- <source>This year</source>
- <translation type="unfinished">Năm nay</translation>
- </message>
- <message>
<source>Other</source>
<translation type="unfinished">Khác</translation>
</message>
<message>
- <source>Enter address, transaction id, or label to search</source>
- <translation type="unfinished">Nhập địa chỉ, số id giao dịch, hoặc nhãn để tìm kiếm</translation>
- </message>
- <message>
- <source>Comma separated file</source>
- <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
- <translation type="unfinished">Tệp tách dấu phẩy</translation>
- </message>
- <message>
- <source>Confirmed</source>
- <translation type="unfinished">Äã xác nhận</translation>
- </message>
- <message>
- <source>Date</source>
- <translation type="unfinished">Ngày</translation>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">Hiển thị trong %1</translation>
</message>
<message>
<source>Label</source>
@@ -2433,80 +1093,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Address</source>
<translation type="unfinished">Äịa chỉ</translation>
</message>
- <message>
- <source>Exporting Failed</source>
- <translation type="unfinished">Xuất Thất Bại</translation>
- </message>
</context>
<context>
- <name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.
-Go to File &gt; Open Wallet to load a wallet.
-- OR -</source>
- <translation type="unfinished">ChÆ°a có ví nào được tải. Äi tá»›i Tệp&gt; Mở Ví để nạp ví.- HOẶC -</translation>
- </message>
- <message>
- <source>Create a new wallet</source>
- <translation type="unfinished">Tạo một ví mới</translation>
- </message>
- <message>
- <source>Error</source>
- <translation type="unfinished">Lá»—i</translation>
- </message>
- <message>
- <source>Load Transaction Data</source>
- <translation type="unfinished">Tải thông tin giao dịch</translation>
- </message>
- <message>
- <source>Partially Signed Transaction (*.psbt)</source>
- <translation type="unfinished">Giao dịch được đăng ký một phần (*.psbt)</translation>
- </message>
- <message>
- <source>PSBT file must be smaller than 100 MiB</source>
- <translation type="unfinished">Tệp PSBT phải nhỠhơn 100 MiB</translation>
- </message>
- <message>
- <source>Unable to decode PSBT</source>
- <translation type="unfinished">Không thể giải mã PSBT</translation>
- </message>
-</context>
-<context>
- <name>WalletModel</name>
- <message>
- <source>Send Coins</source>
- <translation type="unfinished">Gá»­i Coins</translation>
- </message>
- <message>
- <source>Fee bump error</source>
- <translation type="unfinished">Fee bơm error</translation>
- </message>
- <message>
- <source>Can't draft transaction.</source>
- <translation type="unfinished">Không thể tạo tạm giao dịch.</translation>
- </message>
- <message>
- <source>PSBT copied</source>
- <translation type="unfinished">Äã sao chép PSBT</translation>
- </message>
- <message>
- <source>default wallet</source>
- <translation type="unfinished">ví mặc định</translation>
- </message>
-</context>
-<context>
<name>WalletView</name>
<message>
<source>&amp;Export</source>
<translation type="unfinished">&amp;Xuất</translation>
</message>
- <message>
- <source>Export the data in the current tab to a file</source>
- <translation type="unfinished">Xuất dữ liệu trong thẻ hiện tại ra file</translation>
- </message>
- <message>
- <source>Cancel</source>
- <translation type="unfinished">Hủy</translation>
- </message>
-</context>
+ </context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_yo.ts b/src/qt/locale/bitcoin_yo.ts
index 75a8046ab2..893e93b7e0 100644
--- a/src/qt/locale/bitcoin_yo.ts
+++ b/src/qt/locale/bitcoin_yo.ts
@@ -105,6 +105,24 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_zh-Hans.ts b/src/qt/locale/bitcoin_zh-Hans.ts
index 455cdf958a..a135c74e80 100644
--- a/src/qt/locale/bitcoin_zh-Hans.ts
+++ b/src/qt/locale/bitcoin_zh-Hans.ts
@@ -2,95 +2,104 @@
<context>
<name>AddressBookPage</name>
<message>
+ <source>Right-click to edit address or label</source>
+ <translation type="unfinished">é¼ æ ‡å³å‡»ç¼–辑地å€æˆ–标签</translation>
+ </message>
+ <message>
<source>Create a new address</source>
- <translation type="unfinished">创建一个新的地å€</translation>
+ <translation type="unfinished">创建新地å€</translation>
</message>
<message>
<source>&amp;New</source>
- <translation type="unfinished">新建</translation>
+ <translation type="unfinished">新建(&amp;N)</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation type="unfinished">å¤åˆ¶é€‰å®šçš„地å€åˆ°ç³»ç»Ÿå‰ªåˆ‡æ¿</translation>
+ <translation type="unfinished">å¤åˆ¶å½“å‰é€‰ä¸­çš„地å€åˆ°ç³»ç»Ÿå‰ªè´´æ¿</translation>
</message>
<message>
<source>&amp;Copy</source>
- <translation type="unfinished">å¤åˆ¶</translation>
+ <translation type="unfinished">å¤åˆ¶(&amp;C)</translation>
</message>
<message>
<source>C&amp;lose</source>
- <translation type="unfinished">关闭</translation>
+ <translation type="unfinished">关闭(&amp;L)</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation type="unfinished">从列表删除选定的地å€</translation>
+ <translation type="unfinished">从列表中删除选中的地å€</translation>
</message>
<message>
<source>Enter address or label to search</source>
- <translation type="unfinished">输入地å€æˆ–者标签进行æœç´¢</translation>
+ <translation type="unfinished">输入地å€æˆ–标签æ¥æœç´¢</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation type="unfinished">导出当å‰æ•°æ®åˆ°æ–‡ä»¶</translation>
+ <translation type="unfinished">将当å‰æ ‡ç­¾é¡µæ•°æ®å¯¼å‡ºåˆ°æ–‡ä»¶</translation>
</message>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">导出</translation>
+ <translation type="unfinished">导出(&amp;E)</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation type="unfinished">删除</translation>
+ <translation type="unfinished">删除(&amp;D)</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation type="unfinished">选择å‘é€æ¯”特å¸åœ°å€</translation>
+ <translation type="unfinished">选择è¦å‘å¸ç»™å“ªäº›åœ°å€</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation type="unfinished">选择接收比特å¸åœ°å€</translation>
+ <translation type="unfinished">选择è¦ç”¨å“ªäº›åœ°å€æ”¶å¸</translation>
</message>
<message>
<source>C&amp;hoose</source>
- <translation type="unfinished">选择</translation>
+ <translation type="unfinished">选择(&amp;H)</translation>
</message>
<message>
<source>Sending addresses</source>
- <translation type="unfinished">å‘é€åœ°å€</translation>
+ <translation type="unfinished">付款地å€</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation type="unfinished">接收地å€</translation>
+ <translation type="unfinished">收款地å€</translation>
</message>
<message>
<source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
- <translation type="unfinished">这是你的比特å¸å‘å¸åœ°å€ã€‚å‘é€å‰è¯·ç¡®è®¤å‘é€æ•°é‡å’ŒæŽ¥æ”¶åœ°å€</translation>
+ <translation type="unfinished">您å¯ä»¥ç»™è¿™äº›æ¯”特å¸åœ°å€ä»˜æ¬¾ã€‚在付款之å‰ï¼ŒåŠ¡å¿…è¦æ£€æŸ¥é‡‘é¢å’Œæ”¶æ¬¾åœ°å€æ˜¯å¦æ­£ç¡®ã€‚</translation>
</message>
<message>
<source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
Signing is only possible with addresses of the type 'legacy'.</source>
- <translation type="unfinished">这是你的比特å¸æŽ¥æ”¶åœ°å€ã€‚点击接收选项å¡ä¸­â€œåˆ›å»ºæ–°çš„接收地å€â€æŒ‰é’®æ¥åˆ›å»ºæ–°çš„地å€ã€‚
-ç­¾ååªèƒ½ä½¿ç”¨â€œä¼ ç»Ÿâ€ç±»åž‹çš„地å€ã€‚</translation>
+ <translation type="unfinished">这是您用æ¥æ”¶æ¬¾çš„比特å¸åœ°å€ã€‚使用“接收â€æ ‡ç­¾é¡µä¸­çš„“创建新收款地å€â€æŒ‰é’®æ¥åˆ›å»ºæ–°çš„收款地å€ã€‚
+åªæœ‰â€œä¼ ç»Ÿï¼ˆlegacy)â€ç±»åž‹çš„地å€æ”¯æŒç­¾å。</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation type="unfinished">å¤åˆ¶åœ°å€</translation>
+ <translation type="unfinished">å¤åˆ¶åœ°å€(&amp;C)</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation type="unfinished">å¤åˆ¶æ ‡ç­¾</translation>
+ <translation type="unfinished">å¤åˆ¶æ ‡ç­¾(&amp;L)</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation type="unfinished">编辑</translation>
+ <translation type="unfinished">编辑(&amp;E)</translation>
</message>
<message>
<source>Export Address List</source>
<translation type="unfinished">导出地å€åˆ—表</translation>
</message>
<message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">逗å·åˆ†éš”文件</translation>
+ </message>
+ <message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
<extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
- <translation type="unfinished">ä¿å­˜åœ°å€åˆ—表至%1æ—¶å‘生错误,请é‡è¯•ã€‚</translation>
+ <translation type="unfinished">å°è¯•ä¿å­˜åœ°å€åˆ—表到 %1 æ—¶å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -128,7 +137,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Repeat new passphrase</source>
- <translation type="unfinished">é‡å¤è¾“入新密ç </translation>
+ <translation type="unfinished">é‡å¤æ–°å¯†ç </translation>
</message>
<message>
<source>Show passphrase</source>
@@ -140,7 +149,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation type="unfinished">æ­¤æ“作需è¦æ‚¨çš„钱包密ç ç”¨æ¥è§£é”钱包。</translation>
+ <translation type="unfinished">这个æ“作需è¦ä½ çš„钱包密ç æ¥è§£é”钱包。</translation>
</message>
<message>
<source>Unlock wallet</source>
@@ -156,11 +165,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
- <translation type="unfinished">注æ„:如果你加密了钱包åˆå¿˜è®°äº†å¯†ç ï¼Œä½ å°†ä¼šä¸¢å¤±æ‰€æœ‰çš„比特å¸ï¼</translation>
+ <translation type="unfinished">警告: 如果把钱包加密åŽåˆå¿˜è®°å¯†ç ï¼Œä½ å°±ä¼šä»Žæ­¤&lt;b&gt;失去其中所有的比特å¸äº†&lt;/b&gt;ï¼</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation type="unfinished">你确定è¦å°†é’±åŒ…加密å—?</translation>
+ <translation type="unfinished">你确定è¦æŠŠé’±åŒ…加密å—?</translation>
</message>
<message>
<source>Wallet encrypted</source>
@@ -168,160 +177,4450 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<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">输入钱包的新密ç ã€‚&lt;br/&gt;密ç ä¸­è¯·ä½¿ç”¨&lt;b&gt;10个或更多éšæœºå­—符&lt;/b&gt;,或&lt;b&gt;8个或更多的å•è¯&lt;/b&gt;。</translation>
+ <translation type="unfinished">为此钱包输入新密ç ã€‚&lt;br/&gt;请使用由&lt;b&gt;å个或更多的éšæœºå­—符&lt;/b&gt;,或者&lt;b&gt;八个或更多å•è¯&lt;/b&gt;组æˆçš„密ç ã€‚</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
- <translation type="unfinished">输入钱包的旧密ç å’Œæ–°å¯†ç ã€‚</translation>
+ <translation type="unfinished">输入此钱包的旧密ç å’Œæ–°å¯†ç ã€‚</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation type="unfinished">请注æ„,当您的计算机感染æ¶æ„软件时,加密钱包并ä¸èƒ½å®Œå…¨è§„é¿æ‚¨çš„比特å¸è¢«å·çªƒçš„å¯èƒ½ã€‚</translation>
</message>
<message>
<source>Wallet to be encrypted</source>
- <translation type="unfinished">需è¦åŠ å¯†çš„钱包</translation>
+ <translation type="unfinished">è¦åŠ å¯†çš„钱包</translation>
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation type="unfinished">你的钱包将è¦è¢«åŠ å¯†</translation>
+ <translation type="unfinished">您的钱包将è¦è¢«åŠ å¯†ã€‚</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation type="unfinished">你的钱包已被加密</translation>
+ <translation type="unfinished">您的钱包现在已被加密。</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation type="unfinished">é‡è¦: 请用新生æˆçš„ã€å·²åŠ å¯†çš„钱包备份文件å–代你之å‰ç•™çš„钱包文件备份。出于安全方é¢çš„原因,一旦你开始使用新的已加密钱包,旧的未加密钱包文件备份就失效了。</translation>
</message>
<message>
<source>Wallet encryption failed</source>
<translation type="unfinished">钱包加密失败</translation>
</message>
<message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation type="unfinished">因为内部错误导致钱包加密失败。你的钱包还是没加密。</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">æ供的密ç ä¸ä¸€è‡´ã€‚</translation>
+ </message>
+ <message>
<source>Wallet unlock failed</source>
<translation type="unfinished">钱包解é”失败</translation>
</message>
- </context>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation type="unfinished">输入的钱包解é”密ç ä¸æ­£ç¡®ã€‚</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished">钱包密ç ä¿®æ”¹æˆåŠŸã€‚</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished">警告: 大写字æ¯é”定已开å¯ï¼</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation type="unfinished">IP/网络掩ç </translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation type="unfinished">在此之å‰ä¿æŒå°ç¦:</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">设置文件%1å¯èƒ½å·²æŸå或无效。</translation>
+ </message>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">未æ•èŽ·çš„异常</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">å‘生致命错误。%1 å·²ç»æ— æ³•ç»§ç»­å®‰å…¨è¿è¡Œå¹¶å³å°†é€€å‡ºã€‚</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">内部错误</translation>
+ </message>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">å‘生了一个内部错误。%1将会å°è¯•å®‰å…¨åœ°ç»§ç»­è¿è¡Œã€‚关于这个未知的错误我们有以下的æè¿°ä¿¡æ¯ç”¨äºŽå‚考。</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
+ <message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">è¦å°†è®¾ç½®é‡ç½®ä¸ºé»˜è®¤å€¼ï¼Œè¿˜æ˜¯è¦æ”¾å¼ƒæ›´æ”¹å¹¶ä¸­æ­¢ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">出现致命错误。请检查设置文件是å¦å¯å†™ï¼Œæˆ–者å°è¯•å¸¦ -nosettings å‚æ•°è¿è¡Œã€‚</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation type="unfinished">错误:指定的数æ®ç›®å½•â€œ%1â€ä¸å­˜åœ¨ã€‚</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation type="unfinished">错误:无法解æžé…置文件: %1</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">错误: %1</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1 还没有安全退出...</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation type="unfinished">未知</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">金é¢</translation>
+ </message>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation type="unfinished">请输入一个比特å¸åœ°å€ (例如 %1)</translation>
+ </message>
+ <message>
+ <source>Unroutable</source>
+ <translation type="unfinished">ä¸å¯è·¯ç”±</translation>
+ </message>
+ <message>
+ <source>Internal</source>
+ <translation type="unfinished">内部</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
+ <translation type="unfinished">ä¼ å…¥</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <extracomment>An outbound connection to a peer. An outbound connection is a connection initiated by us.</extracomment>
+ <translation type="unfinished">传出</translation>
+ </message>
+ <message>
+ <source>Full Relay</source>
+ <extracomment>Peer connection type that relays all network information.</extracomment>
+ <translation type="unfinished">完整转å‘</translation>
+ </message>
+ <message>
+ <source>Block Relay</source>
+ <extracomment>Peer connection type that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">区å—转å‘</translation>
+ </message>
+ <message>
+ <source>Manual</source>
+ <extracomment>Peer connection type established manually through one of several methods.</extracomment>
+ <translation type="unfinished">手册</translation>
+ </message>
+ <message>
+ <source>Feeler</source>
+ <extracomment>Short-lived peer connection type that tests the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">触须</translation>
+ </message>
+ <message>
+ <source>Address Fetch</source>
+ <extracomment>Short-lived peer connection type that solicits known addresses from a peer.</extracomment>
+ <translation type="unfinished">地å€å–回</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation type="unfinished">%1 天</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation type="unfinished">%1 å°æ—¶</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation type="unfinished">%1 分钟</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation type="unfinished">%1 秒</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation type="unfinished">æ— </translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation type="unfinished">ä¸å¯ç”¨</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation type="unfinished">%1 毫秒</translation>
+ </message>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n秒</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n分钟</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n å°æ—¶</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n 天</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n 周</numerusform>
</translation>
</message>
+ <message>
+ <source>%1 and %2</source>
+ <translation type="unfinished">%1 和 %2</translation>
+ </message>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nå¹´</numerusform>
</translation>
</message>
+ <message>
+ <source>%1 B</source>
+ <translation type="unfinished">%1 字节</translation>
+ </message>
</context>
<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">无法读å–设置文件</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">无法写入设置文件</translation>
+ </message>
+ <message>
+ <source>The %s developers</source>
+ <translation type="unfinished">%s å¼€å‘者</translation>
+ </message>
+ <message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation type="unfinished">%sæŸå。请å°è¯•ç”¨bitcoin-wallet钱包工具æ¥å¯¹å…¶è¿›è¡Œæ€¥æ•‘。或者用一个备份进行还原。</translation>
+ </message>
+ <message>
+ <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
+ <translation type="unfinished">å‚æ•° -maxtxfee 被设置得éžå¸¸é«˜ï¼å³ä½¿æ˜¯å•ç¬”交易也å¯èƒ½ä»˜å‡ºå¦‚此之大的手续费。</translation>
+ </message>
+ <message>
+ <source>Cannot downgrade wallet from version %i to version %i. Wallet version unchanged.</source>
+ <translation type="unfinished">无法把钱包版本从%ié™çº§åˆ°%i。钱包版本未改å˜ã€‚</translation>
+ </message>
+ <message>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation type="unfinished">无法é”定数æ®ç›®å½• %s。%s å¯èƒ½å·²ç»åœ¨è¿è¡Œã€‚</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">无法在ä¸æ”¯æŒâ€œæ‹†åˆ†å‰çš„密钥池â€ï¼ˆpre split keypool)的情况下把“éžæ‹†åˆ†HD钱包â€ï¼ˆnon HD split wallet)从版本%iå‡çº§åˆ°%i。请使用版本å·%i,或者压根ä¸è¦æŒ‡å®šç‰ˆæœ¬å·ã€‚</translation>
+ </message>
+ <message>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation type="unfinished">在MITå议下分å‘,å‚è§é™„带的 %s 或 %s 文件</translation>
+ </message>
+ <message>
+ <source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation type="unfinished">è¯»å– %s æ—¶å‘生错误ï¼æ‰€æœ‰çš„密钥都å¯ä»¥æ­£ç¡®è¯»å–,但是交易记录或地å€ç°¿æ•°æ®å¯èƒ½å·²ç»ä¸¢å¤±æˆ–出错。</translation>
+ </message>
+ <message>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">读å–%s出错ï¼äº¤æ˜“æ•°æ®å¯èƒ½ä¸¢å¤±æˆ–有误。é‡æ–°æ‰«æ钱包中。</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
+ <translation type="unfinished">错误: 转储文件格å¼ä¸æ­£ç¡®ã€‚得到是"%s",而预期本应得到的是 "format"。</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile identifier record is incorrect. Got "%s", expected "%s".</source>
+ <translation type="unfinished">错误: 转储文件标识符记录ä¸æ­£ç¡®ã€‚得到的是 "%s",而预期本应得到的是 "%s"。</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile version is not supported. This version of bitcoin-wallet only supports version 1 dumpfiles. Got dumpfile with version %s</source>
+ <translation type="unfinished">错误: 转储文件版本ä¸è¢«æ”¯æŒã€‚这个版本的 bitcoin-wallet åªæ”¯æŒç‰ˆæœ¬ä¸º 1 的转储文件。得到的转储文件版本å´æ˜¯%s</translation>
+ </message>
+ <message>
+ <source>Error: Legacy wallets only support the "legacy", "p2sh-segwit", and "bech32" address types</source>
+ <translation type="unfinished">错误: 传统钱包åªæ”¯æŒ "legacy", "p2sh-segwit", å’Œ "bech32" 这三ç§åœ°å€ç±»åž‹</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation type="unfinished">手续费估计失败。而且备用手续费估计(fallbackfee)已被ç¦ç”¨ã€‚请å†ç­‰ä¸€äº›åŒºå—,或者通过-fallbackfeeå‚æ•°å¯ç”¨å¤‡ç”¨æ‰‹ç»­è´¹ä¼°è®¡ã€‚</translation>
+ </message>
+ <message>
+ <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">文件%så·²ç»å­˜åœ¨ã€‚如果你确定这就是你想åšçš„,先把这个文件挪开。</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</source>
+ <translation type="unfinished">å‚æ•° -maxtxfee=&lt;amount&gt;: '%s' 指定了éžæ³•çš„é‡‘é¢ (手续费必须至少达到最å°è½¬å‘费率(minrelay fee) %s 以é¿å…交易å¡ç€å‘ä¸å‡ºåŽ»)</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">无效或æŸåçš„peers.dat (%s)。如果你确信这是一个bug,请å馈到%s。作为å˜é€šåŠžæ³•ï¼Œä½ å¯ä»¥æŠŠçŽ°æœ‰æ–‡ä»¶ (%s) 移开(é‡å‘½åã€ç§»åŠ¨æˆ–删除),这样就å¯ä»¥åœ¨ä¸‹æ¬¡å¯åŠ¨æ—¶åˆ›å»ºä¸€ä¸ªæ–°æ–‡ä»¶äº†ã€‚</translation>
+ </message>
+ <message>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation type="unfinished">æ供多个洋葱路由绑定地å€ã€‚对自动创建的洋葱æœåŠ¡ç”¨%s</translation>
+ </message>
+ <message>
+ <source>No dump file provided. To use createfromdump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">没有æ供转储文件。è¦ä½¿ç”¨ createfromdump ,必须æä¾› -dumpfile=&lt;filename&gt;。</translation>
+ </message>
+ <message>
+ <source>No dump file provided. To use dump, -dumpfile=&lt;filename&gt; must be provided.</source>
+ <translation type="unfinished">没有æ供转储文件。è¦ä½¿ç”¨ dump ,必须æä¾› -dumpfile=&lt;filename&gt;。</translation>
+ </message>
+ <message>
+ <source>No wallet file format provided. To use createfromdump, -format=&lt;format&gt; must be provided.</source>
+ <translation type="unfinished">没有æ供钱包格å¼ã€‚è¦ä½¿ç”¨ createfromdump ,必须æä¾› -format=&lt;format&gt;</translation>
+ </message>
+ <message>
+ <source>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</source>
+ <translation type="unfinished">请检查电脑的日期时间设置是å¦æ­£ç¡®ï¼æ—¶é—´é”™è¯¯å¯èƒ½ä¼šå¯¼è‡´ %s è¿è¡Œå¼‚常。</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation type="unfinished">如果你认为%s对你比较有用的è¯ï¼Œè¯·å¯¹æˆ‘们进行一些自愿贡献。请访问%s网站æ¥èŽ·å–有关这个软件的更多信æ¯ã€‚</translation>
+ </message>
+ <message>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation type="unfinished">修剪被设置得太å°ï¼Œå·²ç»ä½ŽäºŽæœ€å°å€¼%d MiB,请使用更大的数值。</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">修剪模å¼ä¸Ž -reindex-chainstate ä¸å…¼å®¹ã€‚请进行一次完整的 -reindex 。</translation>
+ </message>
+ <message>
+ <source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
+ <translation type="unfinished">修剪:上次åŒæ­¥é’±åŒ…çš„ä½ç½®å·²ç»è¶…出(è½åŽäºŽï¼‰çŽ°æœ‰ä¿®å‰ªåŽæ•°æ®çš„范围。你需è¦è¿›è¡Œ-reindex(对于已ç»å¯ç”¨ä¿®å‰ªèŠ‚点,就需è¦é‡æ–°ä¸‹è½½æ•´ä¸ªåŒºå—链)</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation type="unfinished">SQLiteDatabase: SQLite钱包schema版本%d未知。åªæ”¯æŒ%d版本</translation>
+ </message>
+ <message>
+ <source>The block database contains a block which appears to be from the future. This may be due to your computer's date and time being set incorrectly. Only rebuild the block database if you are sure that your computer's date and time are correct</source>
+ <translation type="unfinished">区å—æ•°æ®åº“包å«æœªæ¥çš„交易,这å¯èƒ½æ˜¯ç”±æœ¬æœºé”™è¯¯çš„日期时间引起。若确认本机日期时间正确,请é‡æ–°å»ºç«‹åŒºå—æ•°æ®åº“。</translation>
+ </message>
+ <message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">区å—索引数æ®åº“å«æœ‰åŽ†å²é—留的 'txindex' 。å¯ä»¥è¿è¡Œå®Œæ•´çš„ -reindex æ¥æ¸…ç†è¢«å ç”¨çš„ç£ç›˜ç©ºé—´ï¼›ä¹Ÿå¯ä»¥å¿½ç•¥è¿™ä¸ªé”™è¯¯ã€‚这个错误消æ¯å°†ä¸ä¼šå†æ¬¡æ˜¾ç¤ºã€‚</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation type="unfinished">这笔交易在扣除手续费åŽçš„金é¢å¤ªå°ï¼Œä»¥è‡³äºŽæ— æ³•é€å‡º</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">如果这个钱包之å‰æ²¡æœ‰æ­£ç¡®å…³é—­ï¼Œè€Œä¸”上一次是被新版的Berkeley DB加载过,就会å‘生这个错误。如果是这样,请使用上次加载过这个钱包的那个软件。</translation>
+ </message>
+ <message>
+ <source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
+ <translation type="unfinished">这是测试用的预å‘布版本 - 请谨慎使用 - ä¸è¦ç”¨æ¥æŒ–矿,或者在正å¼å•†ç”¨çŽ¯å¢ƒä¸‹ä½¿ç”¨</translation>
+ </message>
+ <message>
+ <source>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</source>
+ <translation type="unfinished">为了在常规选å¸è¿‡ç¨‹ä¸­ä¼˜å…ˆè€ƒè™‘é¿å…“åªèŠ±å‡ºä¸€ä¸ªåœ°å€ä¸Šçš„一部分å¸â€ï¼ˆpartial spend)这ç§æƒ…况,您最多还需è¦ï¼ˆåœ¨å¸¸è§„手续费之外)付出的交易手续费。</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation type="unfinished">找零低于当å‰ç²‰å°˜é˜ˆå€¼æ—¶ä¼šè¢«èˆå¼ƒï¼Œå¹¶è®¡å…¥æ‰‹ç»­è´¹ï¼Œè¿™äº›äº¤æ˜“手续费就是在这ç§æƒ…况下产生的。</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation type="unfinished">ä¸èƒ½ä¼°è®¡æ‰‹ç»­è´¹æ—¶ï¼Œä½ ä¼šä»˜å‡ºè¿™ä¸ªæ‰‹ç»­è´¹é‡‘é¢ã€‚</translation>
+ </message>
+ <message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation type="unfinished">网络版本字符串的总长度 (%i) 超过最大长度 (%i) 了。请å‡å°‘ uacomment å‚数的数目或长度。</translation>
+ </message>
+ <message>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation type="unfinished">无法é‡æ”¾åŒºå—。你需è¦å…ˆç”¨-reindex-chainstateå‚æ•°æ¥é‡å»ºæ•°æ®åº“。</translation>
+ </message>
+ <message>
+ <source>Unknown wallet file format "%s" provided. Please provide one of "bdb" or "sqlite".</source>
+ <translation type="unfinished">æä¾›äº†æœªçŸ¥çš„é’±åŒ…æ ¼å¼ "%s" 。请使用 "bdb" 或 "sqlite" 中的一ç§ã€‚</translation>
+ </message>
+ <message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">找到了ä¸å—支æŒçš„ chainstate æ•°æ®åº“æ ¼å¼ã€‚请使用 -reindex-chainstate å‚æ•°é‡å¯ã€‚这将会é‡å»º chainstate æ•°æ®åº“。</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">钱包创建æˆåŠŸã€‚æ—§å¼é’±åŒ…已被弃用,未æ¥å°†ä¸å†æ”¯æŒåˆ›å»ºæˆ–打开旧å¼é’±åŒ…。</translation>
+ </message>
+ <message>
+ <source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
+ <translation type="unfinished">警告: è½¬å‚¨æ–‡ä»¶çš„é’±åŒ…æ ¼å¼ "%s" ä¸Žå‘½ä»¤è¡ŒæŒ‡å®šçš„æ ¼å¼ "%s" ä¸ç¬¦ã€‚</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation type="unfinished">警告:在已ç»ç¦ç”¨ç§é’¥çš„钱包 {%s} 中ä»ç„¶æ£€æµ‹åˆ°ç§é’¥</translation>
+ </message>
+ <message>
+ <source>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</source>
+ <translation type="unfinished">警告:我们和其他节点似乎没达æˆå…±è¯†ï¼æ‚¨å¯èƒ½éœ€è¦å‡çº§ï¼Œæˆ–者就是其他节点å¯èƒ½éœ€è¦å‡çº§ã€‚</translation>
+ </message>
+ <message>
+ <source>Witness data for blocks after height %d requires validation. Please restart with -reindex.</source>
+ <translation type="unfinished">需è¦éªŒè¯é«˜åº¦åœ¨%d之åŽçš„区å—è§è¯æ•°æ®ã€‚请使用 -reindex é‡æ–°å¯åŠ¨ã€‚</translation>
+ </message>
+ <message>
+ <source>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</source>
+ <translation type="unfinished">您需è¦ä½¿ç”¨ -reindex é‡æ–°æž„建数æ®åº“以回到未修剪模å¼ã€‚这将é‡æ–°ä¸‹è½½æ•´ä¸ªåŒºå—链</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation type="unfinished">%séžå¸¸é«˜ï¼</translation>
+ </message>
+ <message>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation type="unfinished">-maxmempool 最å°ä¸º%d MB</translation>
+ </message>
+ <message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation type="unfinished">å‘生了致命的内部错误,请在debug.log中查看详情</translation>
+ </message>
+ <message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation type="unfinished">æ— æ³•è§£æž - %s 地å€: '%s'</translation>
+ </message>
+ <message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">在 -dnsseed 被设为 false 时无法将 -forcednsseed 设为 true 。</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation type="unfinished">没有å¯ç”¨-blockfilterindex,就ä¸èƒ½å¯ç”¨-peerblockfilters。</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation type="unfinished">ä¸èƒ½å†™å…¥åˆ°æ•°æ®ç›®å½•'%s';请检查文件æƒé™ã€‚</translation>
+ </message>
+ <message>
+ <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">无法完æˆç”±ä¹‹å‰ç‰ˆæœ¬å¯åŠ¨çš„ -txindex å‡çº§ã€‚请用之å‰çš„版本é‡æ–°å¯åŠ¨ï¼Œæˆ–者进行一次完整的 -reindex 。</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s请求监å¬ç«¯å£ %u。这个端å£è¢«è®¤ä¸ºæ˜¯â€œåçš„â€ï¼Œæ‰€ä»¥ä¸å¤ªå¯èƒ½æœ‰Bitcoin Core节点会连接到它。有关详细信æ¯å’Œå®Œæ•´åˆ—表,请å‚è§ doc/p2p-bad-ports.md 。</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate 与 -blockfilterindex ä¸å…¼å®¹ã€‚请在进行 -reindex-chainstate 时临时ç¦ç”¨ blockfilterindex ,或者改用 -reindex (而ä¸æ˜¯ -reindex-chainstate )æ¥å®Œæ•´åœ°é‡å»ºæ‰€æœ‰ç´¢å¼•ã€‚</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate 与 -coinstatsindex ä¸å…¼å®¹ã€‚请在进行 -reindex-chainstate 时临时ç¦ç”¨ coinstatsindex ,或者改用 -reindex (而ä¸æ˜¯ -reindex-chainstate )æ¥å®Œæ•´åœ°é‡å»ºæ‰€æœ‰ç´¢å¼•ã€‚</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate 与 -txindex ä¸å…¼å®¹ã€‚请在进行 -reindex-chainstate 时临时ç¦ç”¨ txindex ,或者改用 -reindex (而ä¸æ˜¯ -reindex-chainstate )æ¥å®Œæ•´åœ°é‡å»ºæ‰€æœ‰ç´¢å¼•ã€‚</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">å‡å®šæœ‰æ•ˆï¼ˆassume-valid): 上次åŒæ­¥é’±åŒ…时进度越过了现有的区å—æ•°æ®ã€‚你需è¦ç­‰å¾…åŽå°éªŒè¯é“¾ä¸‹è½½æ›´å¤šçš„区å—。</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">在使用地å€ç®¡ç†å™¨(addrman)寻找出站连接时,无法åŒæ—¶æ供特定的连接。</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">加载%s时出错: 编译时未å¯ç”¨å¤–部签å器支æŒï¼Œå´ä»ç„¶è¯•å›¾åŠ è½½å¤–部签å器钱包</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">错误:钱包中的地å€ç°¿æ•°æ®æ— æ³•è¢«è¯†åˆ«ä¸ºå±žäºŽè¿ç§»åŽçš„钱包</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">错误:è¿ç§»è¿‡ç¨‹ä¸­åˆ›å»ºäº†é‡å¤çš„输出æ述符。你的钱包å¯èƒ½å·²æŸå。</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">错误:钱包中的交易%s无法被识别为属于è¿ç§»åŽçš„钱包</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">错误:无法为这个é—留钱包生æˆè¾“出æ述符。请先确定钱包已被解é”</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">无法é‡å‘½å无效的 peers.dat 文件。 请移动或删除它,然åŽé‡è¯•ã€‚</translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">互ä¸å…¼å®¹çš„选项:-dnsseed=1 已被显å¼æŒ‡å®šï¼Œä½† -onlynet ç¦æ­¢äº†IPv4/IPv6 连接</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">出站连接被é™åˆ¶ä¸ºä»…使用 Tor (-onlynet=onion),但是到达 Tor 网络的代ç†è¢«æ˜¾å¼ç¦æ­¢ï¼š -onion=0</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">出站连接被é™åˆ¶ä¸ºä»…使用 Tor (-onlynet=onion),但是未æ供到达 Tor 网络的代ç†ï¼šæ²¡æœ‰æä¾› -proxy=, -onion= 或 -listenonion å‚æ•°</translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">找到无法识别的输出æ述符。加载钱包%s
+
+钱包å¯èƒ½ç”±æ–°ç‰ˆè½¯ä»¶åˆ›å»ºï¼Œ
+请å°è¯•è¿è¡Œæœ€æ–°çš„软件版本。
+</translation>
+ </message>
+ <message>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished">ä¸æ”¯æŒçš„类别é™å®šæ—¥å¿—等级 -loglevel=%s。预期å‚æ•° -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s。有效的类别: %s。</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+无法清ç†å¤±è´¥çš„è¿ç§»</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+无法还原钱包备份</translation>
+ </message>
+ <message>
+ <source>Config setting for %s only applied on %s network when in [%s] section.</source>
+ <translation type="unfinished">对 %s çš„é…置设置åªå¯¹ %s 网络生效,如果它ä½äºŽé…置的 [%s] 章节的è¯ã€‚</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation type="unfinished">版æƒæ‰€æœ‰ (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation type="unfinished">检测到区å—æ•°æ®åº“æŸå</translation>
+ </message>
+ <message>
+ <source>Could not find asmap file %s</source>
+ <translation type="unfinished">找ä¸åˆ°asmap文件%s</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation type="unfinished">无法解æžasmap文件%s</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation type="unfinished">ç£ç›˜ç©ºé—´å¤ªä½Ž!</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation type="unfinished">你想现在就é‡å»ºåŒºå—æ•°æ®åº“å—?</translation>
+ </message>
+ <message>
+ <source>Done loading</source>
+ <translation type="unfinished">加载完æˆ</translation>
+ </message>
+ <message>
+ <source>Dump file %s does not exist.</source>
+ <translation type="unfinished">转储文件 %s ä¸å­˜åœ¨</translation>
+ </message>
+ <message>
+ <source>Error creating %s</source>
+ <translation type="unfinished">创建%s时出错</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation type="unfinished">åˆå§‹åŒ–区å—æ•°æ®åº“时出错</translation>
+ </message>
+ <message>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation type="unfinished">åˆå§‹åŒ–钱包数æ®åº“环境错误 %s!</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation type="unfinished">载入 %s æ—¶å‘生错误</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation type="unfinished">加载 %s 时出错:åªèƒ½åœ¨åˆ›å»ºé’±åŒ…æ—¶ç¦ç”¨ç§é’¥ã€‚</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation type="unfinished">%s 加载出错:钱包æŸå</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation type="unfinished">%s 加载错误:请å‡çº§åˆ°æœ€æ–°ç‰ˆ %s</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation type="unfinished">加载区å—æ•°æ®åº“时出错</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation type="unfinished">打开区å—æ•°æ®åº“时出错</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation type="unfinished">读å–æ•°æ®åº“出错,关闭中。</translation>
+ </message>
+ <message>
+ <source>Error reading next record from wallet database</source>
+ <translation type="unfinished">从钱包数æ®åº“读å–下一æ¡è®°å½•æ—¶å‡ºé”™</translation>
+ </message>
+ <message>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">错误:无法添加仅观察交易至仅观察钱包</translation>
+ </message>
+ <message>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">错误:无法删除仅观察交易</translation>
+ </message>
+ <message>
+ <source>Error: Couldn't create cursor into database</source>
+ <translation type="unfinished">错误: 无法在数æ®åº“中创建指针</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low for %s</source>
+ <translation type="unfinished">错误: %s 所在的ç£ç›˜ç©ºé—´ä½Žã€‚</translation>
+ </message>
+ <message>
+ <source>Error: Dumpfile checksum does not match. Computed %s, expected %s</source>
+ <translation type="unfinished">错误: 转储文件的校验和ä¸ç¬¦ã€‚计算得到%s,预料中本应该得到%s</translation>
+ </message>
+ <message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">错误:创建新仅观察钱包失败</translation>
+ </message>
+ <message>
+ <source>Error: Got key that was not hex: %s</source>
+ <translation type="unfinished">错误: 得到了ä¸æ˜¯å六进制的键:%s</translation>
+ </message>
+ <message>
+ <source>Error: Got value that was not hex: %s</source>
+ <translation type="unfinished">错误: 得到了ä¸æ˜¯å六进制的数值:%s</translation>
+ </message>
+ <message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation type="unfinished">错误: 密钥池已被耗尽,请先调用keypoolrefill</translation>
+ </message>
+ <message>
+ <source>Error: Missing checksum</source>
+ <translation type="unfinished">错误:跳过检查检验和</translation>
+ </message>
+ <message>
+ <source>Error: No %s addresses available.</source>
+ <translation type="unfinished">错误: 没有å¯ç”¨çš„%s地å€ã€‚</translation>
+ </message>
+ <message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">错误:有些仅观察交易无法被删除</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">错误:此钱包已ç»åœ¨ä½¿ç”¨SQLite</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">错误:这个钱包已ç»æ˜¯è¾“出æ述符钱包</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">错误:无法开始读å–这个数æ®åº“中的所有记录</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">错误:无法为你的钱包创建备份</translation>
+ </message>
+ <message>
+ <source>Error: Unable to parse version %u as a uint32_t</source>
+ <translation type="unfinished">错误:无法把版本å·%u作为unit32_t解æž</translation>
+ </message>
+ <message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">错误:无法读å–这个数æ®åº“中的所有记录</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">错误:无法移除仅观察地å€ç°¿æ•°æ®</translation>
+ </message>
+ <message>
+ <source>Error: Unable to write record to new wallet</source>
+ <translation type="unfinished">错误: 无法写入记录到新钱包</translation>
+ </message>
+ <message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation type="unfinished">监å¬ç«¯å£å¤±è´¥ã€‚如果你愿æ„çš„è¯ï¼Œè¯·ä½¿ç”¨ -listen=0 å‚数。</translation>
+ </message>
+ <message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation type="unfinished">åˆå§‹åŒ–æ—¶é‡æ‰«æ钱包失败</translation>
+ </message>
+ <message>
+ <source>Failed to verify database</source>
+ <translation type="unfinished">校验数æ®åº“失败</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation type="unfinished">手续费率 (%s) 低于最大手续费率设置 (%s)</translation>
+ </message>
+ <message>
+ <source>Ignoring duplicate -wallet %s.</source>
+ <translation type="unfinished">忽略é‡å¤çš„ -wallet %s。</translation>
+ </message>
+ <message>
+ <source>Importing…</source>
+ <translation type="unfinished">导入...</translation>
+ </message>
+ <message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation type="unfinished">没有找到创世区å—,或者创世区å—ä¸æ­£ç¡®ã€‚是å¦æŠŠæ•°æ®ç›®å½•é”™è¯¯åœ°è®¾æˆäº†å¦ä¸€ä¸ªç½‘络(比如测试网络)的?</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation type="unfinished">åˆå§‹åŒ–完整性检查失败。%s å³å°†å…³é—­ã€‚</translation>
+ </message>
+ <message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">找ä¸åˆ°äº¤æ˜“输入项,å¯èƒ½å·²ç»è¢«èŠ±æŽ‰äº†</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation type="unfinished">金é¢ä¸è¶³</translation>
+ </message>
+ <message>
+ <source>Invalid -i2psam address or hostname: '%s'</source>
+ <translation type="unfinished">无效的 -i2psam 地å€æˆ–主机å: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation type="unfinished">无效的 -onion 地å€: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation type="unfinished">无效的 -proxy 地å€æˆ–主机å: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation type="unfinished">无效的 P2P æƒé™ï¼š'%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation type="unfinished">å‚æ•° -%s=&lt;amount&gt;: '%s' 指定了无效的金é¢</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation type="unfinished">å‚æ•° -discardfee=&lt;amount&gt;: '%s' 指定了无效的金é¢</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation type="unfinished">å‚æ•° -fallbackfee=&lt;amount&gt;: '%s' 指定了无效的金é¢</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
+ <translation type="unfinished">å‚æ•° -paytxfee=&lt;amount&gt; 指定了éžæ³•çš„金é¢: '%s' (必须至少达到 %s)</translation>
+ </message>
+ <message>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation type="unfinished">å‚æ•° -whitelist: '%s' 指定了无效的网络掩ç </translation>
+ </message>
+ <message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">监å¬å¤–部连接失败 (listen函数返回了错误 %s)</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses…</source>
+ <translation type="unfinished">加载P2P地å€...</translation>
+ </message>
+ <message>
+ <source>Loading banlist…</source>
+ <translation type="unfinished">加载å°ç¦åˆ—表...</translation>
+ </message>
+ <message>
+ <source>Loading block index…</source>
+ <translation type="unfinished">加载区å—索引...</translation>
+ </message>
+ <message>
+ <source>Loading wallet…</source>
+ <translation type="unfinished">加载钱包...</translation>
+ </message>
+ <message>
+ <source>Missing amount</source>
+ <translation type="unfinished">找ä¸åˆ°é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">找ä¸åˆ°ç”¨äºŽä¼°è®¡äº¤æ˜“大å°çš„解答数æ®</translation>
+ </message>
+ <message>
+ <source>Need to specify a port with -whitebind: '%s'</source>
+ <translation type="unfinished">-whitebind: '%s' 需è¦æŒ‡å®šä¸€ä¸ªç«¯å£</translation>
+ </message>
+ <message>
+ <source>No addresses available</source>
+ <translation type="unfinished">没有å¯ç”¨çš„地å€</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation type="unfinished">没有足够的文件æ述符å¯ç”¨ã€‚</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation type="unfinished">ä¸èƒ½æŠŠä¿®å‰ªé…ç½®æˆä¸€ä¸ªè´Ÿæ•°ã€‚</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation type="unfinished">修剪模å¼ä¸Ž -txindex ä¸å…¼å®¹ã€‚</translation>
+ </message>
+ <message>
+ <source>Pruning blockstore…</source>
+ <translation type="unfinished">修剪区å—存储...</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation type="unfinished">因为系统的é™åˆ¶ï¼Œå°† -maxconnections å‚数从 %d é™åˆ°äº† %d</translation>
+ </message>
+ <message>
+ <source>Replaying blocks…</source>
+ <translation type="unfinished">é‡æ”¾åŒºå—...</translation>
+ </message>
+ <message>
+ <source>Rescanning…</source>
+ <translation type="unfinished">é‡æ‰«æ...</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation type="unfinished">SQLiteDatabase: 执行校验数æ®åº“语å¥æ—¶å¤±è´¥: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation type="unfinished">SQLiteDatabase: 预处ç†ç”¨äºŽæ ¡éªŒæ•°æ®åº“的语å¥æ—¶å¤±è´¥: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation type="unfinished">SQLiteDatabase: 读å–æ•°æ®åº“失败,校验错误: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation type="unfinished">SQLiteDatabase: æ„料之外的应用ID。预期为%u,实际为%u</translation>
+ </message>
+ <message>
+ <source>Section [%s] is not recognized.</source>
+ <translation type="unfinished">无法识别é…置章节 [%s]。</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation type="unfinished">ç­¾å交易失败</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation type="unfinished">å‚æ•° -walletdir "%s" 指定了ä¸å­˜åœ¨çš„路径</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation type="unfinished">å‚æ•° -walletdir "%s" 指定了相对路径</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation type="unfinished">å‚æ•° -walletdir "%s" 指定的路径ä¸æ˜¯ç›®å½•</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation type="unfinished">指定的区å—目录"%s"ä¸å­˜åœ¨ã€‚</translation>
+ </message>
+ <message>
+ <source>Starting network threads…</source>
+ <translation type="unfinished">å¯åŠ¨ç½‘络线程...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation type="unfinished">å¯ä»¥ä»Ž %s 获å–æºä»£ç ã€‚</translation>
+ </message>
+ <message>
+ <source>The specified config file %s does not exist</source>
+ <translation type="unfinished">指定的é…置文件%sä¸å­˜åœ¨</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation type="unfinished">交易金é¢å¤ªå°ï¼Œä¸è¶³ä»¥æ”¯ä»˜äº¤æ˜“è´¹</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation type="unfinished">钱包会é¿å…让手续费低于最å°è½¬å‘费率(minrelay fee)。</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation type="unfinished">这是实验性的软件。</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation type="unfinished">这是你æ¯æ¬¡äº¤æ˜“付款时最少è¦ä»˜çš„手续费。</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation type="unfinished">如果å‘é€äº¤æ˜“,这将是你è¦æ”¯ä»˜çš„手续费。</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation type="unfinished">交易金é¢å¤ªå°</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation type="unfinished">交易金é¢ä¸ä¸å¯ä¸ºè´Ÿæ•°</translation>
+ </message>
+ <message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">交易找零输出项编å·è¶…出范围</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation type="unfinished">此交易在内存池中的存在过长的链æ¡</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation type="unfinished">交易必须包å«è‡³å°‘一个收款人</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">交易需è¦ä¸€ä¸ªæ‰¾é›¶åœ°å€ï¼Œä½†æ˜¯æˆ‘们无法生æˆå®ƒã€‚</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation type="unfinished">交易过大</translation>
+ </message>
+ <message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">无法为 -maxsigcachesize: '%s' MiB 分é…内存</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation type="unfinished">无法在本机绑定%sç«¯å£ (bind函数返回了错误 %s)</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation type="unfinished">无法在本机绑定 %s 端å£ã€‚%s å¯èƒ½å·²ç»åœ¨è¿è¡Œã€‚</translation>
+ </message>
+ <message>
+ <source>Unable to create the PID file '%s': %s</source>
+ <translation type="unfinished">无法创建PID文件'%s': %s</translation>
+ </message>
+ <message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">无法为外部输入找到UTXO</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation type="unfinished">无法生æˆåˆå§‹å¯†é’¥</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation type="unfinished">无法生æˆå¯†é’¥</translation>
+ </message>
+ <message>
+ <source>Unable to open %s for writing</source>
+ <translation type="unfinished">无法打开%s用于写入</translation>
+ </message>
+ <message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">æ— æ³•è§£æž -maxuploadtarget: '%s'</translation>
+ </message>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation type="unfinished">无法å¯åŠ¨HTTPæœåŠ¡ï¼ŒæŸ¥çœ‹æ—¥å¿—获å–更多信æ¯</translation>
+ </message>
+ <message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">在è¿ç§»å‰æ— æ³•å¸è½½é’±åŒ…</translation>
+ </message>
+ <message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation type="unfinished">未知的 -blockfilterindex 数值 %s。</translation>
+ </message>
+ <message>
+ <source>Unknown address type '%s'</source>
+ <translation type="unfinished">未知的地å€ç±»åž‹ '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation type="unfinished">未知的找零类型 '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation type="unfinished">-onlynet 指定的是未知网络: %s</translation>
+ </message>
+ <message>
+ <source>Unknown new rules activated (versionbit %i)</source>
+ <translation type="unfinished">ä¸æ˜Žçš„交易规则已ç»æ¿€æ´» (versionbit %i)</translation>
+ </message>
+ <message>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">ä¸æ”¯æŒçš„全局日志等级 -loglevel=%s 。有效的数值:%s 。</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">ä¸æ”¯æŒçš„日志分类 %s=%s。</translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation type="unfinished">用户代ç†å¤‡æ³¨(%s)包å«ä¸å®‰å…¨çš„字符。</translation>
+ </message>
+ <message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">验è¯åŒºå—...</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)…</source>
+ <translation type="unfinished">验è¯é’±åŒ…...</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation type="unfinished">钱包需è¦è¢«é‡å†™ï¼šè¯·é‡æ–°å¯åŠ¨%sæ¥å®Œæˆ</translation>
+ </message>
+</context>
+<context>
<name>BitcoinGUI</name>
+ <message>
+ <source>&amp;Overview</source>
+ <translation type="unfinished">概况(&amp;O)</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation type="unfinished">显示钱包概况</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation type="unfinished">交易记录(&amp;T)</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation type="unfinished">æµè§ˆäº¤æ˜“历å²</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation type="unfinished">退出(&amp;X)</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation type="unfinished">退出程åº</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation type="unfinished">关于 %1 (&amp;A)</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation type="unfinished">显示 %1 的相关信æ¯</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation type="unfinished">关于 &amp;Qt</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation type="unfinished">显示 Qt 相关信æ¯</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation type="unfinished">修改%1çš„é…置选项</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">创建一个新的钱包</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">最å°åŒ–(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">钱包:</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <extracomment>A substring of the tooltip.</extracomment>
+ <translation type="unfinished">网络活动已ç¦ç”¨ã€‚</translation>
+ </message>
+ <message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation type="unfinished">代ç†æœåŠ¡å™¨å·²&lt;b&gt;å¯ç”¨&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation type="unfinished">å‘一个比特å¸åœ°å€å‘å¸</translation>
+ </message>
+ <message>
+ <source>Backup wallet to another location</source>
+ <translation type="unfinished">备份钱包到其他ä½ç½®</translation>
+ </message>
+ <message>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation type="unfinished">修改钱包加密密ç </translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation type="unfinished">å‘é€(&amp;S)</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation type="unfinished">接收(&amp;R)</translation>
+ </message>
+ <message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">选项(&amp;O)</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">加密钱包(&amp;E)</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">把你钱包中的ç§é’¥åŠ å¯†</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">备份钱包(&amp;B)</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">修改密ç (&amp;C)</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">ç­¾å消æ¯(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished">用比特å¸åœ°å€å…³è”çš„ç§é’¥ä¸ºæ¶ˆæ¯ç­¾å,以è¯æ˜Žæ‚¨æ‹¥æœ‰è¿™ä¸ªæ¯”特å¸åœ°å€</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">验è¯æ¶ˆæ¯(&amp;V)</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">校验消æ¯ï¼Œç¡®ä¿è¯¥æ¶ˆæ¯æ˜¯ç”±æŒ‡å®šçš„比特å¸åœ°å€æ‰€æœ‰è€…ç­¾åçš„</translation>
+ </message>
+ <message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">从文件加载PSBT(&amp;L)...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">打开&amp;URI...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">关闭钱包...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">创建钱包...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">关闭所有钱包...</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation type="unfinished">文件(&amp;F)</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation type="unfinished">设置(&amp;S)</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation type="unfinished">帮助(&amp;H)</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation type="unfinished">标签页工具æ </translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">åŒæ­¥åŒºå—头 (%1%)…</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">与网络åŒæ­¥...</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">对ç£ç›˜ä¸Šçš„区å—进行索引...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">处ç†ç£ç›˜ä¸Šçš„区å—...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">é‡æ–°ç´¢å¼•ç£ç›˜ä¸Šçš„区å—...</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">连接到节点...</translation>
+ </message>
+ <message>
+ <source>Request payments (generates QR codes and bitcoin: URIs)</source>
+ <translation type="unfinished">请求支付 (生æˆäºŒç»´ç å’Œ bitcoin: URI)</translation>
+ </message>
+ <message>
+ <source>Show the list of used sending addresses and labels</source>
+ <translation type="unfinished">显示用过的付款地å€å’Œæ ‡ç­¾çš„列表</translation>
+ </message>
+ <message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation type="unfinished">显示用过的收款地å€å’Œæ ‡ç­¾çš„列表</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation type="unfinished">命令行选项(&amp;C)</translation>
+ </message>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>已处ç†%n个区å—的交易历å²ã€‚</numerusform>
</translation>
</message>
+ <message>
+ <source>%1 behind</source>
+ <translation type="unfinished">è½åŽ %1</translation>
+ </message>
+ <message>
+ <source>Catching up…</source>
+ <translation type="unfinished">正在追上进度...</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation type="unfinished">最新收到的区å—产生于 %1 之å‰ã€‚</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation type="unfinished">在此之åŽçš„交易尚ä¸å¯è§</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">错误</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation type="unfinished">警告</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation type="unfinished">ä¿¡æ¯</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation type="unfinished">已是最新</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation type="unfinished">加载部分签å比特å¸äº¤æ˜“(PSBT)</translation>
+ </message>
+ <message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">从剪贴æ¿åŠ è½½PSBT(&amp;C)...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation type="unfinished">从剪贴æ¿ä¸­åŠ è½½éƒ¨åˆ†ç­¾å比特å¸äº¤æ˜“(PSBT)</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">节点窗å£</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation type="unfinished">打开节点调试与诊断控制å°</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation type="unfinished">付款地å€(&amp;S)</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation type="unfinished">收款地å€(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation type="unfinished">打开bitcoin:开头的URI</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation type="unfinished">打开钱包</translation>
+ </message>
+ <message>
+ <source>Open a wallet</source>
+ <translation type="unfinished">打开一个钱包</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">å¸è½½é’±åŒ…</translation>
+ </message>
+ <message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">从备份文件æ¢å¤é’±åŒ…</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">关闭所有钱包</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation type="unfinished">显示 %1 帮助信æ¯ï¼ŒèŽ·å–å¯ç”¨å‘½ä»¤è¡Œé€‰é¡¹åˆ—表</translation>
+ </message>
+ <message>
+ <source>&amp;Mask values</source>
+ <translation type="unfinished">é®ä½æ•°å€¼(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation type="unfinished">在“概况â€æ ‡ç­¾é¡µä¸­ä¸æ˜Žæ–‡æ˜¾ç¤ºæ•°å€¼ã€åªæ˜¾ç¤ºæŽ©ç </translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">默认钱包</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation type="unfinished">没有å¯ç”¨çš„钱包</translation>
+ </message>
+ <message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">钱包数æ®</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">加载钱包备份</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">钱包å称</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">窗å£(&amp;W)</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation type="unfinished">缩放</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation type="unfinished">主窗å£</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation type="unfinished">%1 客户端</translation>
+ </message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">éšè—(&amp;H)</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">显示(&amp;H)</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n æ¡åˆ°æ¯”特å¸ç½‘络的活动连接</numerusform>
</translation>
</message>
- </context>
+ <message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">点击查看更多æ“作。</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">显示节点标签</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">ç¦ç”¨ç½‘络活动</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">å¯ç”¨ç½‘络活动</translation>
+ </message>
+ <message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">预åŒæ­¥åŒºå—头 (%1%)…</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">错误: %1</translation>
+ </message>
+ <message>
+ <source>Warning: %1</source>
+ <translation type="unfinished">警告: %1</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation type="unfinished">日期: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation type="unfinished">金é¢: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation type="unfinished">钱包: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation type="unfinished">类型: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation type="unfinished">标签: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation type="unfinished">地å€: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation type="unfinished">é€å‡ºäº¤æ˜“</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation type="unfinished">æµå…¥äº¤æ˜“</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation type="unfinished">HD密钥生æˆ&lt;b&gt;å¯ç”¨&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">HD密钥生æˆ&lt;b&gt;ç¦ç”¨&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation type="unfinished">ç§é’¥&lt;b&gt;ç¦ç”¨&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
+ <translation type="unfinished">钱包已被&lt;b&gt;加密&lt;/b&gt;,当å‰ä¸º&lt;b&gt;解é”&lt;/b&gt;状æ€</translation>
+ </message>
+ <message>
+ <source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
+ <translation type="unfinished">钱包已被&lt;b&gt;加密&lt;/b&gt;,当å‰ä¸º&lt;b&gt;é”定&lt;/b&gt;状æ€</translation>
+ </message>
+ <message>
+ <source>Original message:</source>
+ <translation type="unfinished">原消æ¯:</translation>
+ </message>
+</context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation type="unfinished">金é¢å•ä½ã€‚å•å‡»é€‰æ‹©åˆ«çš„å•ä½ã€‚</translation>
+ </message>
+</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation type="unfinished">手动选å¸</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation type="unfinished">总é‡:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">字节数:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">金é¢:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation type="unfinished">费用:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">粉尘:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">加上交易费用åŽ:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">找零:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation type="unfinished">å…¨(ä¸)选</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation type="unfinished">树状模å¼</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation type="unfinished">列表模å¼</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">金é¢</translation>
+ </message>
+ <message>
+ <source>Received with label</source>
+ <translation type="unfinished">收款标签</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation type="unfinished">收款地å€</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">日期</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation type="unfinished">确认</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">已确认</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">å¤åˆ¶é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">å¤åˆ¶åœ°å€(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">å¤åˆ¶æ ‡ç­¾(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">å¤åˆ¶é‡‘é¢(&amp;A)</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">å¤åˆ¶äº¤æ˜“&amp;ID和输出åºå·</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">é”定未花费(&amp;O)</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">解é”未花费(&amp;U)</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">å¤åˆ¶æ•°ç›®</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">å¤åˆ¶æ‰‹ç»­è´¹</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">å¤åˆ¶å«äº¤æ˜“费的金é¢</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">å¤åˆ¶å­—节数</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">å¤åˆ¶ç²‰å°˜é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">å¤åˆ¶æ‰¾é›¶é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation type="unfinished">(%1å·²é”定)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation type="unfinished">是</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation type="unfinished">å¦</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation type="unfinished">当任何一个收款金é¢å°äºŽç›®å‰çš„粉尘金é¢é˜ˆå€¼æ—¶ï¼Œæ–‡å­—会å˜çº¢è‰²ã€‚</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation type="unfinished">æ¯ä¸ªè¾“å…¥å¯èƒ½æœ‰ +/- %1 èª (satoshi) 的误差。</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(无标签)</translation>
</message>
- </context>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation type="unfinished">æ¥è‡ª %1 的找零 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation type="unfinished">(找零)</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletActivity</name>
+ <message>
+ <source>Create Wallet</source>
+ <extracomment>Title of window indicating the progress of creation of a new wallet.</extracomment>
+ <translation type="unfinished">创建钱包</translation>
+ </message>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">创建钱包&lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation type="unfinished">创建钱包失败</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation type="unfinished">创建钱包警告</translation>
+ </message>
+ <message>
+ <source>Can't list signers</source>
+ <translation type="unfinished">无法列出签å器</translation>
+ </message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">找到的外部签å器太多</translation>
+ </message>
+</context>
+<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">加载钱包</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">加载钱包...</translation>
+ </message>
+</context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>Open wallet failed</source>
+ <translation type="unfinished">打开钱包失败</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation type="unfinished">打开钱包警告</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">默认钱包</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
+ <translation type="unfinished">打开钱包</translation>
+ </message>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the open wallet progress window which indicates to the user which wallet is currently being opened.</extracomment>
+ <translation type="unfinished">打开钱包&lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
+<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…&lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…失败</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…警告</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…消æ¯</translation>
+ </message>
+</context>
+<context>
+ <name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">å¸è½½é’±åŒ…</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation type="unfinished">您确定想è¦å…³é—­é’±åŒ…&lt;i&gt;%1&lt;/i&gt;å—?</translation>
+ </message>
+ <message>
+ <source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
+ <translation type="unfinished">å¯ç”¨ä¿®å‰ªæ—¶ï¼Œå¦‚果一个钱包被å¸è½½å¤ªä¹…,就必须é‡æ–°åŒæ­¥æ•´æ¡åŒºå—链æ‰èƒ½å†æ¬¡åŠ è½½å®ƒã€‚</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation type="unfinished">关闭所有钱包</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation type="unfinished">您确定想è¦å…³é—­æ‰€æœ‰é’±åŒ…å—?</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletDialog</name>
+ <message>
+ <source>Create Wallet</source>
+ <translation type="unfinished">创建钱包</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation type="unfinished">钱包å称</translation>
+ </message>
+ <message>
+ <source>Wallet</source>
+ <translation type="unfinished">钱包</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation type="unfinished">加密钱包。将会使用您指定的密ç å°†é’±åŒ…加密。</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation type="unfinished">加密钱包</translation>
+ </message>
+ <message>
+ <source>Advanced Options</source>
+ <translation type="unfinished">进阶设定</translation>
+ </message>
+ <message>
+ <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">ç¦ç”¨æ­¤é’±åŒ…çš„ç§é’¥ã€‚被ç¦ç”¨ç§é’¥çš„钱包将ä¸ä¼šå«æœ‰ä»»ä½•ç§é’¥ï¼Œè€Œä¸”也ä¸èƒ½å«æœ‰HDç§å­æˆ–导入的ç§é’¥ã€‚作为仅观察钱包,这是比较ç†æƒ³çš„。</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation type="unfinished">ç¦ç”¨ç§é’¥</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">创建一个空白的钱包。空白钱包最åˆä¸å«æœ‰ä»»ä½•ç§é’¥æˆ–脚本。å¯ä»¥ä»¥åŽå†å¯¼å…¥ç§é’¥å’Œåœ°å€ï¼Œæˆ–设置HDç§å­ã€‚</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation type="unfinished">创建空白钱包</translation>
+ </message>
+ <message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation type="unfinished">使用输出æ述符进行scriptPubKey管ç†</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation type="unfinished">输出æ述符钱包</translation>
+ </message>
+ <message>
+ <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>
+ <message>
+ <source>External signer</source>
+ <translation type="unfinished">外部签å器</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation type="unfinished">创建</translation>
+ </message>
+ <message>
+ <source>Compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished">编译时未å¯ç”¨SQLite支æŒï¼ˆè¾“出æ述符钱包需è¦å®ƒï¼‰</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">编译时未å¯ç”¨å¤–部签åæ”¯æŒ (外部签å需è¦è¿™ä¸ªåŠŸèƒ½)</translation>
+ </message>
+</context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation type="unfinished">编辑地å€</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation type="unfinished">标签(&amp;L)</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation type="unfinished">与此地å€å…³è”的标签</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation type="unfinished">与这个列表项关è”的地å€ã€‚åªæœ‰ä»˜æ¬¾åœ°å€æ‰èƒ½è¢«ä¿®æ”¹ï¼ˆæ”¶æ¬¾åœ°å€ä¸èƒ½è¢«ä¿®æ”¹ï¼‰ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation type="unfinished">地å€(&amp;A)</translation>
+ </message>
+ <message>
+ <source>New sending address</source>
+ <translation type="unfinished">新建付款地å€</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation type="unfinished">编辑收款地å€</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation type="unfinished">编辑付款地å€</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation type="unfinished">è¾“å…¥çš„åœ°å€ %1 并ä¸æ˜¯æœ‰æ•ˆçš„比特å¸åœ°å€ã€‚</translation>
+ </message>
+ <message>
+ <source>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</source>
+ <translation type="unfinished">地å€â€œ%1â€å·²ç»å­˜åœ¨ï¼Œå®ƒæ˜¯ä¸€ä¸ªæ”¶æ¬¾åœ°å€ï¼Œæ ‡ç­¾ä¸ºâ€œ%2â€ï¼Œæ‰€ä»¥å®ƒä¸èƒ½ä½œä¸ºä¸€ä¸ªä»˜æ¬¾åœ°å€è¢«æ·»åŠ è¿›æ¥ã€‚</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation type="unfinished">输入的地å€â€œ%1â€å·²ç»å­˜åœ¨äºŽåœ°å€ç°¿ä¸­ï¼Œæ ‡ç­¾ä¸ºâ€œ%2â€ã€‚</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">无法解é”钱包。</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation type="unfinished">生æˆæ–°å¯†é’¥å¤±è´¥ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation type="unfinished">一个新的数æ®ç›®å½•å°†è¢«åˆ›å»ºã€‚</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation type="unfinished">å称</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation type="unfinished">目录已存在。如果您打算在这里创建一个新目录,请添加 %1。</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation type="unfinished">路径已存在,并且ä¸æ˜¯ä¸€ä¸ªç›®å½•ã€‚</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation type="unfinished">无法在此创建数æ®ç›®å½•ã€‚</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
+ <message>
+ <source>Bitcoin</source>
+ <translation type="unfinished">比特å¸</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>å¯ç”¨ç©ºé—´ %n GB</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(éœ€è¦ %n GB的空间)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(ä¿å­˜å®Œæ•´çš„é“¾éœ€è¦ %n GB)</numerusform>
+ </translation>
+ </message>
+ <message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation type="unfinished">此目录中至少会ä¿å­˜ %1 GB çš„æ•°æ®ï¼Œå¹¶ä¸”大å°è¿˜ä¼šéšç€æ—¶é—´å¢žé•¿ã€‚</translation>
+ </message>
+ <message>
+ <source>Approximately %1 GB of data will be stored in this directory.</source>
+ <translation type="unfinished">会在此目录中存储约 %1 GB çš„æ•°æ®ã€‚</translation>
+ </message>
<message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>(足以æ¢å¤ %n 天之内的备份)</numerusform>
</translation>
</message>
- </context>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation type="unfinished">%1 将会下载并存储比特å¸åŒºå—链。</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation type="unfinished">钱包也会被ä¿å­˜åœ¨è¿™ä¸ªç›®å½•ä¸­ã€‚</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation type="unfinished">错误:无法创建指定的数æ®ç›®å½• "%1"</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">错误</translation>
+ </message>
+ <message>
+ <source>Welcome</source>
+ <translation type="unfinished">欢迎</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation type="unfinished">欢迎使用 %1</translation>
+ </message>
+ <message>
+ <source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
+ <translation type="unfinished">由于这是第一次å¯åŠ¨æ­¤ç¨‹åºï¼Œæ‚¨å¯ä»¥é€‰æ‹©%1存储数æ®çš„ä½ç½®</translation>
+ </message>
+ <message>
+ <source>Limit block chain storage to</source>
+ <translation type="unfinished">将区å—链存储é™åˆ¶åˆ°</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">å–消此设置需è¦é‡æ–°ä¸‹è½½æ•´ä¸ªåŒºå—链。先完整下载整æ¡é“¾å†è¿›è¡Œä¿®å‰ªä¼šæ›´å¿«ã€‚这会ç¦ç”¨ä¸€äº›é«˜çº§åŠŸèƒ½ã€‚</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">åˆå§‹åŒ–åŒæ­¥è¿‡ç¨‹æ˜¯éžå¸¸åƒåŠ›çš„,åŒæ—¶å¯èƒ½ä¼šæš´éœ²æ‚¨ä¹‹å‰æ²¡æœ‰æ³¨æ„到的电脑硬件问题。你æ¯æ¬¡å¯åŠ¨%1时,它都会从之å‰ä¸­æ–­çš„地方继续下载。</translation>
+ </message>
+ <message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">当你å•å‡»ç¡®è®¤åŽï¼Œ%1 将会从%4在%3年创始时最早的交易开始,下载并处ç†å®Œæ•´çš„ %4 区å—链 (%2 GB)。</translation>
+ </message>
+ <message>
+ <source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
+ <translation type="unfinished">如果你选择é™åˆ¶åŒºå—链存储大å°ï¼ˆåŒºå—链è£å‰ªæ¨¡å¼ï¼‰ï¼Œç¨‹åºä¾ç„¶ä¼šä¸‹è½½å¹¶å¤„ç†å…¨éƒ¨åŽ†å²æ•°æ®ï¼Œåªæ˜¯ä¸å¿…须的部分会在使用åŽè¢«åˆ é™¤ï¼Œä»¥å ç”¨æœ€å°‘的存储空间。</translation>
+ </message>
+ <message>
+ <source>Use the default data directory</source>
+ <translation type="unfinished">使用默认的数æ®ç›®å½•</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation type="unfinished">使用自定义的数æ®ç›®å½•:</translation>
+ </message>
+</context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation type="unfinished">版本</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation type="unfinished">关于 %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation type="unfinished">命令行选项</translation>
+ </message>
+</context>
+<context>
+ <name>ShutdownWindow</name>
+ <message>
+ <source>%1 is shutting down…</source>
+ <translation type="unfinished">%1正在关闭...</translation>
+ </message>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation type="unfinished">在此窗å£æ¶ˆå¤±å‰ä¸è¦å…³é—­è®¡ç®—机。</translation>
+ </message>
+</context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Form</source>
+ <translation type="unfinished">窗体</translation>
+ </message>
+ <message>
+ <source>Recent transactions may not yet be visible, and therefore your wallet's balance might be incorrect. This information will be correct once your wallet has finished synchronizing with the bitcoin network, as detailed below.</source>
+ <translation type="unfinished">近期交易å¯èƒ½å°šæœªæ˜¾ç¤ºï¼Œå› æ­¤å½“å‰ä½™é¢å¯èƒ½ä¸å‡†ç¡®ã€‚以上信æ¯å°†åœ¨ä¸Žæ¯”特å¸ç½‘络完全åŒæ­¥åŽæ›´æ­£ã€‚详情如下</translation>
+ </message>
+ <message>
+ <source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
+ <translation type="unfinished">å°è¯•ä½¿ç”¨å—未å¯è§äº¤æ˜“å½±å“çš„ä½™é¢å°†ä¸è¢«ç½‘络接å—。</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation type="unfinished">剩余区å—æ•°é‡</translation>
+ </message>
+ <message>
+ <source>Unknown…</source>
+ <translation type="unfinished">未知...</translation>
+ </message>
+ <message>
+ <source>calculating…</source>
+ <translation type="unfinished">计算中...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation type="unfinished">上一区å—时间</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation type="unfinished">进度</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation type="unfinished">æ¯å°æ—¶è¿›åº¦å¢žåŠ </translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation type="unfinished">预计剩余åŒæ­¥æ—¶é—´</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation type="unfinished">éšè—</translation>
+ </message>
+ <message>
+ <source>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</source>
+ <translation type="unfinished">%1ç›®å‰æ­£åœ¨åŒæ­¥ä¸­ã€‚它会从其他节点下载区å—头和区å—æ•°æ®å¹¶è¿›è¡ŒéªŒè¯ï¼Œç›´åˆ°æŠµè¾¾åŒºå—链尖端。</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">未知。åŒæ­¥åŒºå—头(%1, %2%)...</translation>
+ </message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">未知。预åŒæ­¥åŒºå—头 (%1, %2%)…</translation>
+ </message>
+</context>
+<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <source>Open bitcoin URI</source>
+ <translation type="unfinished">打开比特å¸URI</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <extracomment>Tooltip text for button that allows you to paste an address that is in your clipboard.</extracomment>
+ <translation type="unfinished">从剪贴æ¿ç²˜è´´åœ°å€</translation>
+ </message>
+</context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>Options</source>
+ <translation type="unfinished">选项</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation type="unfinished">主è¦(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation type="unfinished">在登入系统åŽè‡ªåŠ¨å¯åŠ¨ %1</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation type="unfinished">系统登入时å¯åŠ¨ %1 (&amp;S)</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">å¯ç”¨åŒºå—修剪会显著å‡å°å­˜å‚¨äº¤æ˜“对ç£ç›˜ç©ºé—´çš„需求。所有的区å—ä»ç„¶ä¼šè¢«å®Œæ•´æ ¡éªŒã€‚å–消这个设置需è¦é‡æ–°ä¸‹è½½æ•´æ¡åŒºå—链。</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation type="unfinished">æ•°æ®åº“缓存大å°(&amp;D)</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation type="unfinished">脚本验è¯çº¿ç¨‹æ•°(&amp;V)</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation type="unfinished">代ç†æœåŠ¡å™¨ IP åœ°å€ (例如 IPv4: 127.0.0.1 / IPv6: ::1)</translation>
+ </message>
+ <message>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation type="unfinished">显示默认的SOCKS5代ç†æ˜¯å¦è¢«ç”¨äºŽåœ¨è¯¥ç±»åž‹çš„网络下连接åŒä¼´ã€‚</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">窗å£è¢«å…³é—­æ—¶æœ€å°åŒ–程åºè€Œä¸æ˜¯é€€å‡ºã€‚当此选项å¯ç”¨æ—¶ï¼Œåªæœ‰åœ¨èœå•ä¸­é€‰æ‹©â€œé€€å‡ºâ€æ—¶æ‰ä¼šè®©ç¨‹åºé€€å‡ºã€‚</translation>
+ </message>
+ <message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">这个对è¯æ¡†ä¸­çš„设置已被如下命令行选项覆盖:</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation type="unfinished">从工作目录下打开é…置文件 %1。</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation type="unfinished">打开é…置文件</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation type="unfinished">æ¢å¤å®¢æˆ·ç«¯çš„缺çœè®¾ç½®</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation type="unfinished">æ¢å¤ç¼ºçœè®¾ç½®(&amp;R)</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation type="unfinished">网络(&amp;N)</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation type="unfinished">将区å—存储修剪至(&amp;B)</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation type="unfinished">警告:还原此设置需è¦é‡æ–°ä¸‹è½½æ•´ä¸ªåŒºå—链。</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">æ•°æ®åº“缓存的最大大å°ã€‚加大缓存有助于加快åŒæ­¥ï¼Œä½†å¯¹äºŽå¤§å¤šæ•°ä½¿ç”¨åœºæ™¯æ¥è¯´ï¼Œç»§ç»­åŠ å¤§åŽæ”¶æ•ˆä¼šè¶Šæ¥è¶Šä¸æ˜Žæ˜¾ã€‚é™ä½Žç¼“存大å°å°†ä¼šå‡å°å†…存使用é‡ã€‚内存池中尚未被使用的那部分内存也会被共享用于这里的数æ®åº“缓存。</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">设置脚本验è¯çº¿ç¨‹çš„æ•°é‡ã€‚负值则表示你想è¦ä¿ç•™ç»™ç³»ç»Ÿçš„核心数é‡ã€‚</translation>
+ </message>
+ <message>
+ <source>(0 = auto, &lt;0 = leave that many cores free)</source>
+ <translation type="unfinished">(0 = 自动, &lt;0 = ä¿æŒæŒ‡å®šæ•°é‡çš„CPU核心空闲)</translation>
+ </message>
+ <message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">è¿™å…许作为用户的你或第三方工具通过命令行和JSON-RPC命令行与节点通信。</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">å¯ç”¨R&amp;PCæœåŠ¡å™¨</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation type="unfinished">钱包(&amp;A)</translation>
+ </message>
+ <message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">是å¦è¦é»˜è®¤ä»Žé‡‘é¢ä¸­å‡åŽ»æ‰‹ç»­è´¹ã€‚</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">默认从金é¢ä¸­å‡åŽ»äº¤æ˜“手续费(&amp;F)</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation type="unfinished">专家</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation type="unfinished">å¯ç”¨æ‰‹åŠ¨é€‰å¸åŠŸèƒ½(&amp;C)</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">如果您ç¦æ­¢åŠ¨ç”¨å°šæœªç¡®è®¤çš„找零资金,则一笔交易的找零资金至少需è¦æœ‰1个确认åŽæ‰èƒ½åŠ¨ç”¨ã€‚è¿™åŒæ—¶ä¹Ÿä¼šå½±å“账户余é¢çš„计算。</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation type="unfinished">动用尚未确认的找零资金(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">å¯ç”¨&amp;PSBT控件</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">是å¦è¦æ˜¾ç¤ºPSBT控件</translation>
+ </message>
+ <message>
+ <source>External Signer (e.g. hardware wallet)</source>
+ <translation type="unfinished">外部签å器(例如硬件钱包)</translation>
+ </message>
+ <message>
+ <source>&amp;External signer script path</source>
+ <translation type="unfinished">外部签å器脚本路径(&amp;E)</translation>
+ </message>
+ <message>
+ <source>Full path to a Bitcoin Core compatible script (e.g. C:\Downloads\hwi.exe or /Users/you/Downloads/hwi.py). Beware: malware can steal your coins!</source>
+ <translation type="unfinished">指å‘兼容Bitcoin Core的脚本的完整路径 (例如 C:\Downloads\hwi.exe 或者 /Users/you/Downloads/hwi.py )。注æ„: æ¶æ„软件å¯èƒ½ä¼šå·çªƒæ‚¨çš„å¸ï¼</translation>
+ </message>
+ <message>
+ <source>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</source>
+ <translation type="unfinished">自动在路由器中为比特å¸å®¢æˆ·ç«¯æ‰“开端å£ã€‚åªæœ‰å½“您的路由器开å¯äº† UPnP 选项时此功能æ‰ä¼šæœ‰ç”¨ã€‚</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation type="unfinished">使用 &amp;UPnP 映射端å£</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">自动在路由器中为比特å¸å®¢æˆ·ç«¯æ‰“开端å£ã€‚åªæœ‰å½“æ‚¨çš„è·¯ç”±å™¨æ”¯æŒ NAT-PMP 功能并开å¯å®ƒï¼Œè¿™ä¸ªåŠŸèƒ½æ‰ä¼šæ­£å¸¸å·¥ä½œã€‚外边端å£å¯ä»¥æ˜¯éšæœºçš„。</translation>
+ </message>
+ <message>
+ <source>Map port using NA&amp;T-PMP</source>
+ <translation type="unfinished">使用 NA&amp;T-PMP 映射端å£</translation>
+ </message>
+ <message>
+ <source>Accept connections from outside.</source>
+ <translation type="unfinished">接å—外部连接。</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation type="unfinished">å…许传入连接(&amp;G)</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation type="unfinished">通过 SOCKS5 代ç†è¿žæŽ¥æ¯”特å¸ç½‘络。</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation type="unfinished">通过 SO&amp;CKS5 代ç†è¿žæŽ¥(默认代ç†):</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation type="unfinished">代ç†æœåŠ¡å™¨ &amp;IP:</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation type="unfinished">端å£(&amp;P):</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation type="unfinished">代ç†æœåŠ¡å™¨ç«¯å£ï¼ˆä¾‹å¦‚ 9050)</translation>
+ </message>
+ <message>
+ <source>Used for reaching peers via:</source>
+ <translation type="unfinished">在走这些途径连接到节点的时候å¯ç”¨:</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">窗å£(&amp;W)</translation>
+ </message>
+ <message>
+ <source>Show the icon in the system tray.</source>
+ <translation type="unfinished">在通知区域显示图标。</translation>
+ </message>
+ <message>
+ <source>&amp;Show tray icon</source>
+ <translation type="unfinished">显示通知区域图标(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation type="unfinished">最å°åŒ–窗å£åŽä»…显示托盘图标</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation type="unfinished">最å°åŒ–到托盘(&amp;M)</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation type="unfinished">å•å‡»å…³é—­æŒ‰é’®æ—¶æœ€å°åŒ–(&amp;I)</translation>
+ </message>
+ <message>
+ <source>&amp;Display</source>
+ <translation type="unfinished">显示(&amp;D)</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation type="unfinished">用户界é¢è¯­è¨€(&amp;L):</translation>
+ </message>
+ <message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation type="unfinished">å¯ä»¥åœ¨è¿™é‡Œè®¾å®šç”¨æˆ·ç•Œé¢çš„语言。这个设定在é‡å¯ %1 åŽæ‰ä¼šç”Ÿæ•ˆã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation type="unfinished">比特å¸é‡‘é¢å•ä½(&amp;U):</translation>
+ </message>
+ <message>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation type="unfinished">选择显示åŠå‘é€æ¯”特å¸æ—¶ä½¿ç”¨çš„最å°å•ä½ã€‚</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">这个第三方网å€ï¼ˆæ¯”如区å—æµè§ˆå™¨ï¼‰ä¼šå‡ºçŽ°åœ¨äº¤æ˜“选项å¡çš„å³é”®èœå•ä¸­ã€‚ 网å€ä¸­çš„%s代表交易哈希。多个网å€éœ€è¦ç”¨ç«–线 | 相互分隔。</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">第三方交易网å€(&amp;T)</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation type="unfinished">是å¦æ˜¾ç¤ºæ‰‹åŠ¨é€‰å¸åŠŸèƒ½ã€‚</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation type="unfinished">连接比特å¸ç½‘络时专门为Tor onionæœåŠ¡ä½¿ç”¨å¦ä¸€ä¸ª SOCKS5 代ç†ã€‚</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation type="unfinished">连接Tor onionæœåŠ¡èŠ‚点时使用å¦ä¸€ä¸ªSOCKS&amp;5代ç†ï¼š</translation>
+ </message>
+ <message>
+ <source>Monospaced font in the Overview tab:</source>
+ <translation type="unfinished">在概览标签页的等宽字体:</translation>
+ </message>
+ <message>
+ <source>embedded "%1"</source>
+ <translation type="unfinished">嵌入了 “%1â€</translation>
+ </message>
+ <message>
+ <source>closest matching "%1"</source>
+ <translation type="unfinished">与 "%1" 最接近的匹é…</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation type="unfinished">确定(&amp;O)</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation type="unfinished">å–消(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Compiled without external signing support (required for external signing)</source>
+ <extracomment>"External signing" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">编译时未å¯ç”¨å¤–部签åæ”¯æŒ (外部签å需è¦è¿™ä¸ªåŠŸèƒ½)</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation type="unfinished">默认</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation type="unfinished">æ— </translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
+ <translation type="unfinished">确认æ¢å¤é»˜è®¤è®¾ç½®</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
+ <translation type="unfinished">需è¦é‡å¯å®¢æˆ·ç«¯æ‰èƒ½ä½¿æ›´æ”¹ç”Ÿæ•ˆã€‚</translation>
+ </message>
+ <message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">当å‰è®¾ç½®å°†ä¼šè¢«å¤‡ä»½åˆ° "%1"。</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
+ <translation type="unfinished">客户端å³å°†å…³é—­ï¼Œæ‚¨æƒ³ç»§ç»­å—?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <extracomment>Window title text of pop-up box that allows opening up of configuration file.</extracomment>
+ <translation type="unfinished">é…置选项</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>Explanatory text about the priority order of instructions considered by client. The order from high to low being: command-line, configuration file, GUI settings.</extracomment>
+ <translation type="unfinished">é…置文件å¯ä»¥ç”¨æ¥è®¾ç½®é«˜çº§é€‰é¡¹ã€‚é…置文件会覆盖设置界é¢çª—å£ä¸­çš„选项。此外,命令行会覆盖é…置文件指定的选项。</translation>
+ </message>
+ <message>
+ <source>Continue</source>
+ <translation type="unfinished">继续</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation type="unfinished">å–消</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">错误</translation>
+ </message>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation type="unfinished">无法打开é…置文件。</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation type="unfinished">此更改需è¦é‡å¯å®¢æˆ·ç«¯ã€‚</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation type="unfinished">æ供的代ç†æœåŠ¡å™¨åœ°å€æ— æ•ˆã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">无法读å–设置 "%1",%2。</translation>
+ </message>
+</context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation type="unfinished">窗体</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">现在显示的消æ¯å¯èƒ½æ˜¯è¿‡æœŸçš„。在连接上比特å¸ç½‘络节点åŽï¼Œæ‚¨çš„钱包将自动与网络åŒæ­¥ï¼Œä½†æ˜¯è¿™ä¸ªè¿‡ç¨‹è¿˜æ²¡æœ‰å®Œæˆã€‚</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation type="unfinished">仅观察:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation type="unfinished">å¯ä½¿ç”¨çš„ä½™é¢:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation type="unfinished">您当å‰å¯ä½¿ç”¨çš„ä½™é¢</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation type="unfinished">等待中的余é¢:</translation>
+ </message>
+ <message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation type="unfinished">尚未确认的交易总é¢ï¼Œæœªè®¡å…¥å½“å‰ä½™é¢</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation type="unfinished">未æˆç†Ÿçš„:</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation type="unfinished">尚未æˆç†Ÿçš„挖矿收入余é¢</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation type="unfinished">ä½™é¢</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation type="unfinished">总é¢:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation type="unfinished">您当å‰çš„总余é¢</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation type="unfinished">您当å‰åœ¨ä»…观察观察地å€ä¸­çš„ä½™é¢</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation type="unfinished">å¯åŠ¨ç”¨:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation type="unfinished">最近交易</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation type="unfinished">仅观察地å€çš„未确认交易</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation type="unfinished">仅观察地å€ä¸­å°šæœªæˆç†Ÿçš„挖矿收入余é¢:</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation type="unfinished">仅观察地å€ä¸­çš„当å‰æ€»ä½™é¢</translation>
+ </message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation type="unfinished">“概况â€æ ‡ç­¾é¡µå·²å¯ç”¨éšç§æ¨¡å¼ã€‚è¦æ˜Žæ–‡æ˜¾ç¤ºæ•°å€¼ï¼Œè¯·åœ¨è®¾ç½®ä¸­å–消勾选“ä¸æ˜Žæ–‡æ˜¾ç¤ºæ•°å€¼â€ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation type="unfinished">会è¯</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation type="unfinished">ç­¾å交易</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation type="unfinished">广播交易</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation type="unfinished">å¤åˆ¶åˆ°å‰ªè´´æ¿</translation>
+ </message>
+ <message>
+ <source>Save…</source>
+ <translation type="unfinished">ä¿å­˜...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation type="unfinished">关闭</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation type="unfinished">加载交易失败: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation type="unfinished">ç­¾å交易失败: %1</translation>
+ </message>
+ <message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">钱包已é”定,无法签å交易输入项。</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation type="unfinished">没有交易输入项å¯ä¾›ç­¾å了。</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation type="unfinished">已签å %1 个交易输入项,但是ä»ç„¶è¿˜æœ‰ä½™ä¸‹çš„项目需è¦ç­¾å。</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation type="unfinished">æˆåŠŸç­¾å交易。交易已ç»å¯ä»¥å¹¿æ’­ã€‚</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation type="unfinished">处ç†äº¤æ˜“æ—¶é‡åˆ°æœªçŸ¥é”™è¯¯ã€‚</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation type="unfinished">å·²æˆåŠŸå¹¿æ’­äº¤æ˜“ï¼äº¤æ˜“ID: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation type="unfinished">交易广播失败: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation type="unfinished">å·²å¤åˆ¶PSBT到剪贴æ¿</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation type="unfinished">ä¿å­˜äº¤æ˜“æ•°æ®</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">部分签å交易(二进制)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation type="unfinished">PSBTå·²ä¿å­˜åˆ°ç¡¬ç›˜</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation type="unfinished"> * å‘é€ %1 至 %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation type="unfinished">无法计算交易费用或总交易金é¢ã€‚</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation type="unfinished">支付交易费用:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation type="unfinished">总é¢</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation type="unfinished">或</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation type="unfinished">交易中å«æœ‰%1个未签å输入项。</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation type="unfinished">交易中有输入项缺失æŸäº›ä¿¡æ¯ã€‚</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation type="unfinished">交易ä»ç„¶éœ€è¦ç­¾å。</translation>
+ </message>
+ <message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(但没有加载钱包。)</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation type="unfinished">(但这个钱包ä¸èƒ½ç­¾å交易)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation type="unfinished">(但这个钱包没有正确的密钥)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation type="unfinished">交易已ç»å®Œå…¨ç­¾å,å¯ä»¥å¹¿æ’­ã€‚</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation type="unfinished">交易状æ€æœªçŸ¥ã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation type="unfinished">支付请求出错</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation type="unfinished">无法å¯åŠ¨ bitcoin: å议的“一键支付â€å¤„ç†ç¨‹åº</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation type="unfinished">URI 处ç†</translation>
+ </message>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation type="unfinished">‘bitcoin://’ä¸æ˜¯åˆæ³•çš„URI。请改用'bitcoin:'。</translation>
+ </message>
+ <message>
+ <source>Cannot process payment request because BIP70 is not supported.
+Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.
+If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation type="unfinished">因为ä¸æ”¯æŒBIP70,无法处ç†ä»˜æ¬¾è¯·æ±‚。
+由于BIP70具有广泛的安全缺陷,无论哪个商家指引è¦æ±‚您更æ¢é’±åŒ…,我们都强烈建议您ä¸è¦å¬ä¿¡ã€‚
+如果您看到了这个错误,您应该è¦æ±‚商家æ供兼容BIP21çš„URI。</translation>
+ </message>
+ <message>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation type="unfinished">æ— æ³•è§£æž URI 地å€ï¼å¯èƒ½æ˜¯å› ä¸ºæ¯”特å¸åœ°å€æ— æ•ˆï¼Œæˆ–是 URI å‚æ•°æ ¼å¼é”™è¯¯ã€‚</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation type="unfinished">支付请求文件处ç†</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>User Agent</source>
+ <extracomment>Title of Peers Table column which contains the peer's User Agent string.</extracomment>
+ <translation type="unfinished">用户代ç†</translation>
+ </message>
+ <message>
+ <source>Peer</source>
+ <extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
+ <translation type="unfinished">节点</translation>
+ </message>
+ <message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">连接时间</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
+ <translation type="unfinished">æ–¹å‘</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <extracomment>Title of Peers Table column which indicates the total amount of network information we have sent to the peer.</extracomment>
+ <translation type="unfinished">å·²å‘é€</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <extracomment>Title of Peers Table column which indicates the total amount of network information we have received from the peer.</extracomment>
+ <translation type="unfinished">已接收</translation>
+ </message>
+ <message>
<source>Address</source>
<extracomment>Title of Peers Table column which contains the IP/Onion/I2P address of the connected peer.</extracomment>
<translation type="unfinished">地å€</translation>
</message>
- </context>
+ <message>
+ <source>Type</source>
+ <extracomment>Title of Peers Table column which describes the type of peer connection. The "type" describes why the connection exists.</extracomment>
+ <translation type="unfinished">类型</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <extracomment>Title of Peers Table column which states the network the peer connected through.</extracomment>
+ <translation type="unfinished">网络</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <extracomment>An Inbound Connection from a Peer.</extracomment>
+ <translation type="unfinished">ä¼ å…¥</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <extracomment>An Outbound Connection to a Peer.</extracomment>
+ <translation type="unfinished">传出</translation>
+ </message>
+</context>
+<context>
+ <name>QRImageWidget</name>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">ä¿å­˜å›¾åƒ(&amp;S)...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation type="unfinished">å¤åˆ¶å›¾åƒ(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation type="unfinished">URI 太长,请试ç€ç²¾ç®€æ ‡ç­¾æˆ–消æ¯æ–‡æœ¬ã€‚</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation type="unfinished">把 URI ç¼–ç æˆäºŒç»´ç æ—¶å‘生错误。</translation>
+ </message>
+ <message>
+ <source>QR code support not available.</source>
+ <translation type="unfinished">ä¸æ”¯æŒäºŒç»´ç ã€‚</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation type="unfinished">ä¿å­˜äºŒç»´ç </translation>
+ </message>
+ <message>
+ <source>PNG Image</source>
+ <extracomment>Expanded name of the PNG file format. See: https://en.wikipedia.org/wiki/Portable_Network_Graphics.</extracomment>
+ <translation type="unfinished">PNG图åƒ</translation>
+ </message>
+</context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>N/A</source>
+ <translation type="unfinished">ä¸å¯ç”¨</translation>
+ </message>
+ <message>
+ <source>Client version</source>
+ <translation type="unfinished">客户端版本</translation>
+ </message>
+ <message>
+ <source>&amp;Information</source>
+ <translation type="unfinished">ä¿¡æ¯(&amp;I)</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation type="unfinished">常规</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation type="unfinished">æ•°æ®ç›®å½•</translation>
+ </message>
+ <message>
+ <source>To specify a non-default location of the data directory use the '%1' option.</source>
+ <translation type="unfinished">如果ä¸æƒ³ç”¨é»˜è®¤çš„æ•°æ®ç›®å½•ä½ç½®ï¼Œè¯·ç”¨ '%1' 这个选项æ¥æŒ‡å®šæ–°çš„ä½ç½®ã€‚</translation>
+ </message>
+ <message>
+ <source>Blocksdir</source>
+ <translation type="unfinished">区å—存储目录</translation>
+ </message>
+ <message>
+ <source>To specify a non-default location of the blocks directory use the '%1' option.</source>
+ <translation type="unfinished">如果è¦è‡ªå®šä¹‰åŒºå—存储目录的ä½ç½®ï¼Œè¯·ç”¨ '%1' 这个选项æ¥æŒ‡å®šæ–°çš„ä½ç½®ã€‚</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation type="unfinished">å¯åŠ¨æ—¶é—´</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation type="unfinished">网络</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation type="unfinished">å称</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation type="unfinished">连接数</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation type="unfinished">区å—链</translation>
+ </message>
+ <message>
+ <source>Memory Pool</source>
+ <translation type="unfinished">内存池</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation type="unfinished">当å‰äº¤æ˜“æ•°é‡</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation type="unfinished">内存使用</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation type="unfinished">钱包:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation type="unfinished">(æ— )</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation type="unfinished">é‡ç½®(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation type="unfinished">已接收</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation type="unfinished">å·²å‘é€</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation type="unfinished">节点(&amp;P)</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation type="unfinished">å·²å°ç¦èŠ‚点</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation type="unfinished">选择节点查看详细信æ¯ã€‚</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation type="unfinished">版本</translation>
+ </message>
+ <message>
+ <source>Starting Block</source>
+ <translation type="unfinished">起步区å—</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation type="unfinished">å·²åŒæ­¥åŒºå—头</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation type="unfinished">å·²åŒæ­¥åŒºå—</translation>
+ </message>
+ <message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">最近交易</translation>
+ </message>
+ <message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation type="unfinished">映射到的自治系统,被用æ¥å¤šæ ·åŒ–选择节点</translation>
+ </message>
+ <message>
+ <source>Mapped AS</source>
+ <translation type="unfinished">映射到的AS</translation>
+ </message>
+ <message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">是å¦æŠŠåœ°å€è½¬å‘给这个节点。</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">地å€è½¬å‘</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">从这个节点接收并处ç†è¿‡çš„地å€æ€»æ•°ï¼ˆé™¤åŽ»å› é¢‘次é™åˆ¶è€Œä¸¢å¼ƒçš„那些地å€ï¼‰ã€‚</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">从这个节点接收åŽåˆå› é¢‘次é™åˆ¶è€Œä¸¢å¼ƒï¼ˆæœªè¢«å¤„ç†ï¼‰çš„地å€æ€»æ•°ã€‚</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">已处ç†åœ°å€</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">被频率é™åˆ¶ä¸¢å¼ƒçš„地å€</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation type="unfinished">用户代ç†</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">节点窗å£</translation>
+ </message>
+ <message>
+ <source>Current block height</source>
+ <translation type="unfinished">当å‰åŒºå—高度</translation>
+ </message>
+ <message>
+ <source>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</source>
+ <translation type="unfinished">打开当å‰æ•°æ®ç›®å½•ä¸­çš„ %1 调试日志文件。日志文件大的è¯å¯èƒ½è¦ç­‰ä¸Šå‡ ç§’钟。</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation type="unfinished">缩å°å­—体大å°</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation type="unfinished">放大字体大å°</translation>
+ </message>
+ <message>
+ <source>Permissions</source>
+ <translation type="unfinished">æƒé™</translation>
+ </message>
+ <message>
+ <source>The direction and type of peer connection: %1</source>
+ <translation type="unfinished">节点连接的方å‘和类型: %1</translation>
+ </message>
+ <message>
+ <source>Direction/Type</source>
+ <translation type="unfinished">æ–¹å‘/类型</translation>
+ </message>
+ <message>
+ <source>The network protocol this peer is connected through: IPv4, IPv6, Onion, I2P, or CJDNS.</source>
+ <translation type="unfinished">这个节点是通过这ç§ç½‘络å议连接到的: IPv4, IPv6, Onion, I2P, 或 CJDNS.</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation type="unfinished">æœåŠ¡</translation>
+ </message>
+ <message>
+ <source>Whether the peer requested us to relay transactions.</source>
+ <translation type="unfinished">这个节点是å¦è¦æ±‚我们转å‘交易。</translation>
+ </message>
+ <message>
+ <source>Wants Tx Relay</source>
+ <translation type="unfinished">è¦æ±‚交易转å‘</translation>
+ </message>
+ <message>
+ <source>High bandwidth BIP152 compact block relay: %1</source>
+ <translation type="unfinished">高带宽BIP152密实区å—转å‘: %1</translation>
+ </message>
+ <message>
+ <source>High Bandwidth</source>
+ <translation type="unfinished">高带宽</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation type="unfinished">连接时间</translation>
+ </message>
+ <message>
+ <source>Elapsed time since a novel block passing initial validity checks was received from this peer.</source>
+ <translation type="unfinished">自从这个节点上一次å‘æ¥å¯é€šè¿‡åˆå§‹æœ‰æ•ˆæ€§æ£€æŸ¥çš„新区å—以æ¥åˆ°çŽ°åœ¨ç»è¿‡çš„时间</translation>
+ </message>
+ <message>
+ <source>Last Block</source>
+ <translation type="unfinished">上一个区å—</translation>
+ </message>
+ <message>
+ <source>Elapsed time since a novel transaction accepted into our mempool was received from this peer.</source>
+ <extracomment>Tooltip text for the Last Transaction field in the peer details area.</extracomment>
+ <translation type="unfinished">自从这个节点上一次å‘æ¥è¢«æˆ‘们的内存池接å—的新交易到现在ç»è¿‡çš„时间</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation type="unfinished">上次å‘é€</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation type="unfinished">上次接收</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation type="unfinished">Ping 延时</translation>
+ </message>
+ <message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation type="unfinished">ç›®å‰è¿™ä¸€æ¬¡ ping å·²ç»è¿‡åŽ»çš„时间。</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation type="unfinished">Ping 等待</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation type="unfinished">æœ€å° Ping 值</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation type="unfinished">时间å移</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation type="unfinished">上一区å—时间</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation type="unfinished">打开(&amp;O)</translation>
+ </message>
+ <message>
+ <source>&amp;Console</source>
+ <translation type="unfinished">控制å°(&amp;C)</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation type="unfinished">网络æµé‡(&amp;N)</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation type="unfinished">总数</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation type="unfinished">调试日志文件</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation type="unfinished">清空控制å°</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation type="unfinished">ä¼ å…¥:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation type="unfinished">传出:</translation>
+ </message>
+ <message>
+ <source>Inbound: initiated by peer</source>
+ <extracomment>Explanatory text for an inbound peer connection.</extracomment>
+ <translation type="unfinished">入站: 由对端å‘èµ·</translation>
+ </message>
+ <message>
+ <source>Outbound Full Relay: default</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays all network information. This is the default behavior for outbound connections.</extracomment>
+ <translation type="unfinished">出站完整转å‘: 默认</translation>
+ </message>
+ <message>
+ <source>Outbound Block Relay: does not relay transactions or addresses</source>
+ <extracomment>Explanatory text for an outbound peer connection that relays network information about blocks and not transactions or addresses.</extracomment>
+ <translation type="unfinished">出站区å—转å‘: ä¸è½¬å‘交易和地å€</translation>
+ </message>
+ <message>
+ <source>Outbound Manual: added using RPC %1 or %2/%3 configuration options</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">出站手动: 加入使用RPC %1 或 %2/%3 é…置选项</translation>
+ </message>
+ <message>
+ <source>Outbound Feeler: short-lived, for testing addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to test the aliveness of known addresses.</extracomment>
+ <translation type="unfinished">出站触须: 短暂,用于测试地å€</translation>
+ </message>
+ <message>
+ <source>Outbound Address Fetch: short-lived, for soliciting addresses</source>
+ <extracomment>Explanatory text for a short-lived outbound peer connection that is used to request addresses from a peer.</extracomment>
+ <translation type="unfinished">出站地å€å–回: 短暂,用于请求å–回地å€</translation>
+ </message>
+ <message>
+ <source>we selected the peer for high bandwidth relay</source>
+ <translation type="unfinished">我们选择了用于高带宽转å‘的节点</translation>
+ </message>
+ <message>
+ <source>the peer selected us for high bandwidth relay</source>
+ <translation type="unfinished">对端选择了我们用于高带宽转å‘</translation>
+ </message>
+ <message>
+ <source>no high bandwidth relay selected</source>
+ <translation type="unfinished">未选择高带宽转å‘</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">å¤åˆ¶åœ°å€(&amp;C)</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation type="unfinished">æ–­å¼€(&amp;D)</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation type="unfinished">1 å°æ—¶(&amp;H)</translation>
+ </message>
+ <message>
+ <source>1 d&amp;ay</source>
+ <translation type="unfinished">1 天(&amp;A)</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation type="unfinished">1 周(&amp;W)</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation type="unfinished">1 å¹´(&amp;Y)</translation>
+ </message>
+ <message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">å¤åˆ¶IP/网络掩ç (&amp;C)</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation type="unfinished">解å°(&amp;U)</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation type="unfinished">网络活动已ç¦ç”¨</translation>
+ </message>
+ <message>
+ <source>Executing command without any wallet</source>
+ <translation type="unfinished">ä¸ä½¿ç”¨ä»»ä½•é’±åŒ…执行命令</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation type="unfinished">使用“%1â€é’±åŒ…执行命令</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.
+Use up and down arrows to navigate history, and %2 to clear screen.
+Use %3 and %4 to increase or decrease the font size.
+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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">欢迎æ¥åˆ° %1 RPC 控制å°ã€‚
+使用上与下箭头以进行历å²å¯¼èˆªï¼Œ%2 以清除å±å¹•ã€‚
+使用%3 å’Œ %4 以增加或å‡å°å­—体大å°ã€‚
+输入 %5 以显示å¯ç”¨å‘½ä»¤çš„概览。
+查看更多关于此控制å°çš„ä¿¡æ¯ï¼Œè¾“å…¥ %6。
+
+%7 警告:骗å­ä»¬å¾ˆæ´»è·ƒï¼Œå‘Šè¯‰ç”¨æˆ·åœ¨è¿™é‡Œè¾“入命令,å·èµ°ä»–们钱包中的内容。ä¸è¦åœ¨ä¸å®Œå…¨äº†è§£ä¸€ä¸ªå‘½ä»¤çš„åŽæžœçš„情况下使用此控制å°ã€‚%8</translation>
+ </message>
+ <message>
+ <source>Executing…</source>
+ <extracomment>A console message indicating an entered command is currently being executed.</extracomment>
+ <translation type="unfinished">执行中……</translation>
+ </message>
+ <message>
+ <source>(peer: %1)</source>
+ <translation type="unfinished">(节点: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation type="unfinished">通过 %1</translation>
+ </message>
+ <message>
+ <source>Yes</source>
+ <translation type="unfinished">是</translation>
+ </message>
+ <message>
+ <source>No</source>
+ <translation type="unfinished">å¦</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation type="unfinished">到</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation type="unfinished">æ¥è‡ª</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation type="unfinished">å°ç¦æ—¶é•¿</translation>
+ </message>
+ <message>
+ <source>Never</source>
+ <translation type="unfinished">æ°¸ä¸</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation type="unfinished">未知</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Amount:</source>
+ <translation type="unfinished">金é¢(&amp;A):</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation type="unfinished">标签(&amp;L):</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation type="unfinished">消æ¯(&amp;M):</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">å¯åœ¨æ”¯ä»˜è¯·æ±‚上备注一æ¡ä¿¡æ¯ï¼Œåœ¨æ‰“开支付请求时å¯ä»¥çœ‹åˆ°ã€‚注æ„:该消æ¯ä¸æ˜¯é€šè¿‡æ¯”特å¸ç½‘络传é€ã€‚</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation type="unfinished">å¯ä¸ºæ–°å»ºçš„收款地å€æ·»åŠ ä¸€ä¸ªæ ‡ç­¾ã€‚</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation type="unfinished">使用此表å•è¯·æ±‚付款。所有字段都是&lt;b&gt;å¯é€‰&lt;/b&gt;的。</translation>
+ </message>
+ <message>
+ <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
+ <translation type="unfinished">å¯é€‰çš„请求金é¢ã€‚留空或填零为ä¸è¦æ±‚具体金é¢ã€‚</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">一个关è”到新收款地å€ï¼ˆè¢«æ‚¨ç”¨æ¥è¯†åˆ«å‘票)的å¯é€‰æ ‡ç­¾ã€‚它也会被附加到付款请求中。</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation type="unfinished">一æ¡é™„加到付款请求中的å¯é€‰æ¶ˆæ¯ï¼Œå¯ä»¥æ˜¾ç¤ºç»™ä»˜æ¬¾æ–¹ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation type="unfinished">新建收款地å€(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation type="unfinished">清除此表å•çš„所有字段。</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation type="unfinished">清除</translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation type="unfinished">付款请求历å²</translation>
+ </message>
+ <message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation type="unfinished">显示选中的请求 (直接åŒå‡»é¡¹ç›®ä¹Ÿå¯ä»¥æ˜¾ç¤º)</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation type="unfinished">显示</translation>
+ </message>
+ <message>
+ <source>Remove the selected entries from the list</source>
+ <translation type="unfinished">从列表中移除选中的æ¡ç›®</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation type="unfinished">移除</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation type="unfinished">å¤åˆ¶ &amp;URI</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">å¤åˆ¶åœ°å€(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">å¤åˆ¶æ ‡ç­¾(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Copy &amp;message</source>
+ <translation type="unfinished">å¤åˆ¶æ¶ˆæ¯(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">å¤åˆ¶é‡‘é¢(&amp;A)</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation type="unfinished">无法解é”钱包。</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation type="unfinished">无法生æˆæ–°çš„%1地å€</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Request payment to …</source>
+ <translation type="unfinished">请求支付至...</translation>
+ </message>
+ <message>
+ <source>Address:</source>
+ <translation type="unfinished">地å€:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">金é¢:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation type="unfinished">标签:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation type="unfinished">消æ¯:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation type="unfinished">钱包:</translation>
+ </message>
+ <message>
+ <source>Copy &amp;URI</source>
+ <translation type="unfinished">å¤åˆ¶ &amp;URI</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Address</source>
+ <translation type="unfinished">å¤åˆ¶åœ°å€(&amp;A)</translation>
+ </message>
+ <message>
+ <source>&amp;Verify</source>
+ <translation type="unfinished">验è¯(&amp;V)</translation>
+ </message>
+ <message>
+ <source>Verify this address on e.g. a hardware wallet screen</source>
+ <translation type="unfinished">在åƒæ˜¯ç¡¬ä»¶é’±åŒ…å±å¹•çš„地方检验这个地å€</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image…</source>
+ <translation type="unfinished">ä¿å­˜å›¾åƒ(&amp;S)...</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation type="unfinished">付款信æ¯</translation>
+ </message>
+ <message>
+ <source>Request payment to %1</source>
+ <translation type="unfinished">请求付款到 %1</translation>
+ </message>
+</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation type="unfinished">日期</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">标签</translation>
</message>
<message>
+ <source>Message</source>
+ <translation type="unfinished">消æ¯</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(无标签)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation type="unfinished">(无消æ¯)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation type="unfinished">(未填写请求金é¢)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation type="unfinished">请求金é¢</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
+ <message>
+ <source>Send Coins</source>
+ <translation type="unfinished">å‘å¸</translation>
+ </message>
+ <message>
+ <source>Coin Control Features</source>
+ <translation type="unfinished">手动选å¸åŠŸèƒ½</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation type="unfinished">自动选择</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation type="unfinished">金é¢ä¸è¶³ï¼</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation type="unfinished">总é‡:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation type="unfinished">字节数:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation type="unfinished">金é¢:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation type="unfinished">费用:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation type="unfinished">加上交易费用åŽ:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation type="unfinished">找零:</translation>
+ </message>
+ <message>
+ <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
+ <translation type="unfinished">在激活该选项åŽï¼Œå¦‚果填写了无效的找零地å€ï¼Œæˆ–者干脆没填找零地å€ï¼Œæ‰¾é›¶èµ„金将会被转入新生æˆçš„地å€ã€‚</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation type="unfinished">自定义找零地å€</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation type="unfinished">交易手续费:</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">如果使用备用手续费设置,有å¯èƒ½ä¼šå¯¼è‡´äº¤æ˜“ç»è¿‡å‡ ä¸ªå°æ—¶ã€å‡ å¤©ï¼ˆç”šè‡³æ°¸è¿œï¼‰æ— æ³•è¢«ç¡®è®¤ã€‚请考虑手动选择手续费,或等待整个链完æˆéªŒè¯ã€‚</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation type="unfinished">警告: ç›®å‰æ— æ³•è¿›è¡Œæ‰‹ç»­è´¹ä¼°è®¡ã€‚</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation type="unfinished">æ¯KB</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation type="unfinished">éšè—</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation type="unfinished">推è:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation type="unfinished">自定义:</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation type="unfinished">一次å‘é€ç»™å¤šä¸ªæ”¶æ¬¾äºº</translation>
+ </message>
+ <message>
+ <source>Add &amp;Recipient</source>
+ <translation type="unfinished">添加收款人(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation type="unfinished">清除此表å•çš„所有字段。</translation>
+ </message>
+ <message>
+ <source>Inputs…</source>
+ <translation type="unfinished">输入...</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation type="unfinished">粉尘:</translation>
+ </message>
+ <message>
+ <source>Choose…</source>
+ <translation type="unfinished">选择...</translation>
+ </message>
+ <message>
+ <source>Hide transaction fee settings</source>
+ <translation type="unfinished">éšè—交易手续费设置</translation>
+ </message>
+ <message>
+ <source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
+
+Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satoshis per kvB" for a transaction size of 500 virtual bytes (half of 1 kvB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation type="unfinished">指定交易虚拟大å°çš„æ¯kB (1,000字节) 自定义费率。
+
+附注:因为矿工费是按字节计费的,所以如果费率是“æ¯kvB支付100èªâ€ï¼Œé‚£ä¹ˆå¯¹äºŽä¸€ç¬”500虚拟字节 (1kvB的一åŠ) 的交易,最终将åªä¼šäº§ç”Ÿ50èªçš„矿工费。(译注:这里就是æ醒å•ä½æ˜¯å­—节,而ä¸æ˜¯åƒå­—节,如果æžé”™çš„è¯ï¼ŒçŸ¿å·¥è´¹ä¼šè¿‡ä½Žï¼Œå¯¼è‡´äº¤æ˜“长时间无法确认,或者压根无法å‘出)</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">当交易é‡å°äºŽå¯ç”¨åŒºå—空间时,矿工和中继节点å¯èƒ½ä¼šæ‰§è¡Œæœ€ä½Žæ‰‹ç»­è´¹çŽ‡é™åˆ¶ã€‚按照这个最低费率æ¥æ”¯ä»˜æ‰‹ç»­è´¹ä¹Ÿæ˜¯å¯ä»¥çš„,但请注æ„,一旦交易需求超出比特å¸ç½‘络能处ç†çš„é™åº¦ï¼Œä½ çš„交易å¯èƒ½æ°¸è¿œä¹Ÿæ— æ³•ç¡®è®¤ã€‚</translation>
+ </message>
+ <message>
+ <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
+ <translation type="unfinished">过低的手续费率å¯èƒ½å¯¼è‡´äº¤æ˜“永远无法确认(请阅读工具æ示)</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks…)</source>
+ <translation type="unfinished">(智能矿工费尚未被åˆå§‹åŒ–。这一般需è¦å‡ ä¸ªåŒºå—...)</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation type="unfinished">确认时间目标:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation type="unfinished">å¯ç”¨æ‰‹ç»­è´¹è¿½åŠ </translation>
+ </message>
+ <message>
+ <source>With Replace-By-Fee (BIP-125) you can increase a transaction's fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
+ <translation type="unfinished">手续费追加(Replace-By-Fee,BIP-125)å¯ä»¥è®©ä½ åœ¨é€å‡ºäº¤æ˜“åŽç»§ç»­è¿½åŠ æ‰‹ç»­è´¹ã€‚ä¸ç”¨è¿™ä¸ªåŠŸèƒ½çš„è¯ï¼Œå»ºè®®ä»˜æ¯”较高的手续费æ¥é™ä½Žäº¤æ˜“延迟的风险。</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished">清除所有(&amp;A)</translation>
+ </message>
+ <message>
+ <source>Balance:</source>
+ <translation type="unfinished">ä½™é¢:</translation>
+ </message>
+ <message>
+ <source>Confirm the send action</source>
+ <translation type="unfinished">确认å‘é€æ“作</translation>
+ </message>
+ <message>
+ <source>S&amp;end</source>
+ <translation type="unfinished">å‘é€(&amp;E)</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation type="unfinished">å¤åˆ¶æ•°ç›®</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">å¤åˆ¶é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">å¤åˆ¶æ‰‹ç»­è´¹</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation type="unfinished">å¤åˆ¶å«äº¤æ˜“费的金é¢</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation type="unfinished">å¤åˆ¶å­—节数</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation type="unfinished">å¤åˆ¶ç²‰å°˜é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation type="unfinished">å¤åˆ¶æ‰¾é›¶é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation type="unfinished">%1 (%2个å—)</translation>
+ </message>
+ <message>
+ <source>Sign on device</source>
+ <extracomment>"device" usually means a hardware wallet.</extracomment>
+ <translation type="unfinished">在设备上签å</translation>
+ </message>
+ <message>
+ <source>Connect your hardware wallet first.</source>
+ <translation type="unfinished">请先连接您的硬件钱包。</translation>
+ </message>
+ <message>
+ <source>Set external signer script path in Options -&gt; Wallet</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">在 选项 -&gt; 钱包 中设置外部签å器脚本路径</translation>
+ </message>
+ <message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation type="unfinished">创建未签å交易(&amp;E)</translation>
+ </message>
+ <message>
+ <source>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
+ <translation type="unfinished">创建一个“部分签å比特å¸äº¤æ˜“â€ï¼ˆPSBT),以用于诸如离线%1钱包,或是兼容PSBT的硬件钱包这类用途。</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation type="unfinished">从钱包%1</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation type="unfinished">%1 到 '%2'</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation type="unfinished">%1 到 %2</translation>
+ </message>
+ <message>
+ <source>To review recipient list click "Show Details…"</source>
+ <translation type="unfinished">点击“查看详情â€ä»¥å®¡æ ¸æ”¶æ¬¾äººåˆ—表</translation>
+ </message>
+ <message>
+ <source>Sign failed</source>
+ <translation type="unfinished">ç­¾å失败</translation>
+ </message>
+ <message>
+ <source>External signer not found</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">未找到外部签å器</translation>
+ </message>
+ <message>
+ <source>External signer failure</source>
+ <extracomment>"External signer" means using devices such as hardware wallets.</extracomment>
+ <translation type="unfinished">外部签å器失败</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation type="unfinished">ä¿å­˜äº¤æ˜“æ•°æ®</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary)</source>
+ <extracomment>Expanded name of the binary PSBT file format. See: BIP 174.</extracomment>
+ <translation type="unfinished">部分签å交易(二进制)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation type="unfinished">å·²ä¿å­˜PSBT</translation>
+ </message>
+ <message>
+ <source>External balance:</source>
+ <translation type="unfinished">外部余é¢:</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation type="unfinished">或</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation type="unfinished">ä½ å¯ä»¥åŽæ¥å†è¿½åŠ æ‰‹ç»­è´¹ï¼ˆæ‰“上支æŒBIP-125手续费追加的标记)</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">请务必仔细检查您的交易请求。这会产生一个部分签å比特å¸äº¤æ˜“(PSBT),å¯ä»¥æŠŠä¿å­˜ä¸‹æ¥æˆ–å¤åˆ¶å‡ºåŽ»ï¼Œç„¶åŽå°±å¯ä»¥å¯¹å®ƒè¿›è¡Œç­¾å,比如用离线%1钱包,或是用兼容PSBT的硬件钱包。</translation>
+ </message>
+ <message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">è¦åˆ›å»ºè¿™ç¬”交易å—?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">请务必仔细检查您的交易。你å¯ä»¥åˆ›å»ºå¹¶å‘é€è¿™ç¬”交易;也å¯ä»¥åˆ›å»ºä¸€ä¸ªâ€œéƒ¨åˆ†ç­¾å比特å¸äº¤æ˜“(PSBT)â€ï¼Œå®ƒå¯ä»¥è¢«ä¿å­˜ä¸‹æ¥æˆ–被å¤åˆ¶å‡ºåŽ»ï¼Œç„¶åŽå°±å¯ä»¥å¯¹å®ƒè¿›è¡Œç­¾å,比如用离线%1钱包,或是用兼容PSBT的硬件钱包。</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
+ <translation type="unfinished">请检查您的交易。</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation type="unfinished">交易手续费</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation type="unfinished">没有打上BIP-125手续费追加的标记。</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation type="unfinished">总é¢</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation type="unfinished">确认å‘å¸</translation>
+ </message>
+ <message>
+ <source>Watch-only balance:</source>
+ <translation type="unfinished">仅观察余é¢:</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation type="unfinished">接收人地å€æ— æ•ˆã€‚请é‡æ–°æ£€æŸ¥ã€‚</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation type="unfinished">支付金é¢å¿…须大于0。</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation type="unfinished">金é¢è¶…出您的余é¢ã€‚</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation type="unfinished">计入 %1 手续费åŽï¼Œé‡‘é¢è¶…出了您的余é¢ã€‚</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation type="unfinished">å‘现é‡å¤åœ°å€:æ¯ä¸ªåœ°å€åº”该åªä½¿ç”¨ä¸€æ¬¡ã€‚</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation type="unfinished">交易创建失败ï¼</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation type="unfinished">超过 %1 的手续费被视为高得离谱。</translation>
+ </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>预计%n个区å—内确认。</numerusform>
</translation>
</message>
<message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation type="unfinished">警告: 比特å¸åœ°å€æ— æ•ˆ</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation type="unfinished">警告:未知的找零地å€</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation type="unfinished">确认自定义找零地å€</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">你选择的找零地å€æœªè¢«åŒ…å«åœ¨æœ¬é’±åŒ…中,你钱包中的部分或全部金é¢å°†è¢«å‘é€è‡³è¯¥åœ°å€ã€‚你确定è¦è¿™æ ·åšå—?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(无标签)</translation>
</message>
</context>
<context>
+ <name>SendCoinsEntry</name>
+ <message>
+ <source>A&amp;mount:</source>
+ <translation type="unfinished">金é¢(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Pay &amp;To:</source>
+ <translation type="unfinished">付给(&amp;T):</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation type="unfinished">标签(&amp;L):</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation type="unfinished">选择以å‰ç”¨è¿‡çš„地å€</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation type="unfinished">付款目的地å€</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation type="unfinished">从剪贴æ¿ç²˜è´´åœ°å€</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation type="unfinished">移除此项</translation>
+ </message>
+ <message>
+ <source>The amount to send in the selected unit</source>
+ <translation type="unfinished">用被选å•ä½è¡¨ç¤ºçš„å¾…å‘é€é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">交易费将从å‘é€é‡‘é¢ä¸­æ‰£é™¤ã€‚接收人收到的比特å¸å°†ä¼šæ¯”您在金é¢æ¡†ä¸­è¾“入的更少。如果选中了多个收件人,交易费平分。</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation type="unfinished">从金é¢ä¸­å‡åŽ»äº¤æ˜“è´¹(&amp;U)</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation type="unfinished">使用全部å¯ç”¨ä½™é¢</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation type="unfinished">消æ¯:</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <translation type="unfinished">请为此地å€è¾“入一个标签以将它加入已用地å€åˆ—表</translation>
+ </message>
+ <message>
+ <source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
+ <translation type="unfinished">bitcoin: URI 附带的备注信æ¯ï¼Œå°†ä¼šå’Œäº¤æ˜“一起存储,备查。 注æ„:该消æ¯ä¸ä¼šé€šè¿‡æ¯”特å¸ç½‘络传输。</translation>
+ </message>
+</context>
+<context>
+ <name>SendConfirmationDialog</name>
+ <message>
+ <source>Send</source>
+ <translation type="unfinished">å‘é€</translation>
+ </message>
+ <message>
+ <source>Create Unsigned</source>
+ <translation type="unfinished">创建未签å交易</translation>
+ </message>
+</context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ <message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation type="unfinished">ç­¾å - 为消æ¯ç­¾å/验è¯ç­¾å消æ¯</translation>
+ </message>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation type="unfinished">消æ¯ç­¾å(&amp;S)</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">您å¯ä»¥ç”¨ä½ çš„地å€å¯¹æ¶ˆæ¯/å议进行签å,以è¯æ˜Žæ‚¨å¯ä»¥æŽ¥æ”¶å‘é€åˆ°è¯¥åœ°å€çš„比特å¸ã€‚注æ„ä¸è¦å¯¹ä»»ä½•æ¨¡æ£±ä¸¤å¯æˆ–者éšæœºçš„消æ¯è¿›è¡Œç­¾å,以å…é­å—é’“é±¼å¼æ”»å‡»ã€‚请确ä¿æ¶ˆæ¯å†…容准确的表达了您的真实æ„愿。</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation type="unfinished">用æ¥å¯¹æ¶ˆæ¯ç­¾å的地å€</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation type="unfinished">选择以å‰ç”¨è¿‡çš„地å€</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation type="unfinished">从剪贴æ¿ç²˜è´´åœ°å€</translation>
+ </message>
+ <message>
+ <source>Enter the message you want to sign here</source>
+ <translation type="unfinished">在这里输入您想è¦ç­¾å的消æ¯</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation type="unfinished">ç­¾å</translation>
+ </message>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation type="unfinished">å¤åˆ¶å½“å‰ç­¾å至剪贴æ¿</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation type="unfinished">ç­¾å消æ¯ï¼Œä»¥è¯æ˜Žè¿™ä¸ªåœ°å€å±žäºŽæ‚¨</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation type="unfinished">ç­¾å消æ¯(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Reset all sign message fields</source>
+ <translation type="unfinished">清空所有签å消æ¯æ </translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation type="unfinished">清除所有(&amp;A)</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation type="unfinished">消æ¯éªŒè¯(&amp;V)</translation>
+ </message>
+ <message>
+ <source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
+ <translation type="unfinished">请在下é¢è¾“入接收者地å€ã€æ¶ˆæ¯ï¼ˆç¡®ä¿æ¢è¡Œç¬¦ã€ç©ºæ ¼ç¬¦ã€åˆ¶è¡¨ç¬¦ç­‰å®Œå…¨ç›¸åŒï¼‰å’Œç­¾å以验è¯æ¶ˆæ¯ã€‚请仔细核对签åä¿¡æ¯ï¼Œä»¥æ防中间人攻击。请注æ„,这åªæ˜¯è¯æ˜ŽæŽ¥æ”¶æ–¹å¯ä»¥ç”¨è¿™ä¸ªåœ°å€ç­¾å,它ä¸èƒ½è¯æ˜Žä»»ä½•äº¤æ˜“çš„å‘é€äººèº«ä»½ï¼</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation type="unfinished">用æ¥ç­¾å消æ¯çš„地å€</translation>
+ </message>
+ <message>
+ <source>The signed message to verify</source>
+ <translation type="unfinished">待验è¯çš„已签å消æ¯</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation type="unfinished">对消æ¯è¿›è¡Œç­¾ç½²å¾—到的签åæ•°æ®</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation type="unfinished">验è¯æ¶ˆæ¯ï¼Œç¡®ä¿æ¶ˆæ¯æ˜¯ç”±æŒ‡å®šçš„比特å¸åœ°å€ç­¾å过的。</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation type="unfinished">验è¯æ¶ˆæ¯ç­¾å(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Reset all verify message fields</source>
+ <translation type="unfinished">清空所有验è¯æ¶ˆæ¯æ </translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation type="unfinished">å•å‡»â€œç­¾å消æ¯â€œäº§ç”Ÿç­¾å。</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation type="unfinished">输入的地å€æ— æ•ˆã€‚</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation type="unfinished">请检查地å€åŽé‡è¯•ã€‚</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation type="unfinished">找ä¸åˆ°ä¸Žè¾“入地å€ç›¸å…³çš„密钥。</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation type="unfinished">å·²å–消解é”钱包。</translation>
+ </message>
+ <message>
+ <source>No error</source>
+ <translation type="unfinished">没有错误</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation type="unfinished">找ä¸åˆ°è¾“入地å€å…³è”çš„ç§é’¥ã€‚</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation type="unfinished">消æ¯ç­¾å失败。</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation type="unfinished">消æ¯å·²ç­¾å。</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation type="unfinished">ç­¾å无法解ç ã€‚</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation type="unfinished">请检查签ååŽé‡è¯•ã€‚</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation type="unfinished">ç­¾å与消æ¯æ‘˜è¦ä¸åŒ¹é…。</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation type="unfinished">消æ¯éªŒè¯å¤±è´¥ã€‚</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation type="unfinished">消æ¯éªŒè¯æˆåŠŸã€‚</translation>
+ </message>
+</context>
+<context>
+ <name>SplashScreen</name>
+ <message>
+ <source>(press q to shutdown and continue later)</source>
+ <translation type="unfinished">(按q退出并在以åŽç»§ç»­)</translation>
+ </message>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">按q键关闭并退出</translation>
+ </message>
+</context>
+<context>
<name>TransactionDesc</name>
+ <message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
+ <translation type="unfinished">与一个有 %1 个确认的交易冲çª</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/未确认,在内存池中</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/未确认,ä¸åœ¨å†…存池中</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
+ <translation type="unfinished">已丢弃</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
+ <translation type="unfinished">%1/未确认</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
+ <translation type="unfinished">%1 个确认</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation type="unfinished">状æ€</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">日期</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation type="unfinished">æ¥æº</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation type="unfinished">挖矿生æˆ</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation type="unfinished">æ¥è‡ª</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation type="unfinished">未知</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation type="unfinished">到</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation type="unfinished">自己的地å€</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation type="unfinished">仅观察:</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation type="unfinished">标签</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation type="unfinished">收入</translation>
+ </message>
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>在%n个区å—内æˆç†Ÿ</numerusform>
</translation>
</message>
- </context>
+ <message>
+ <source>not accepted</source>
+ <translation type="unfinished">未被接å—</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation type="unfinished">支出</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation type="unfinished">总支出</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation type="unfinished">总收入</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation type="unfinished">交易手续费</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation type="unfinished">净é¢</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation type="unfinished">消æ¯</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation type="unfinished">备注</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation type="unfinished">交易 ID</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation type="unfinished">交易总大å°</translation>
+ </message>
+ <message>
+ <source>Transaction virtual size</source>
+ <translation type="unfinished">交易虚拟大å°</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation type="unfinished">输出索引</translation>
+ </message>
+ <message>
+ <source> (Certificate was not verified)</source>
+ <translation type="unfinished">(è¯ä¹¦æœªè¢«éªŒè¯)</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation type="unfinished">商家</translation>
+ </message>
+ <message>
+ <source>Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to "not accepted" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.</source>
+ <translation type="unfinished">新挖出的比特å¸åœ¨å¯ä»¥ä½¿ç”¨å‰å¿…é¡»ç»è¿‡ %1 个区å—确认的æˆç†Ÿè¿‡ç¨‹ã€‚当您挖出此区å—åŽï¼Œå®ƒå°†è¢«å¹¿æ’­åˆ°ç½‘络中以加入区å—链。如果它未æˆåŠŸè¿›å…¥åŒºå—链,其状æ€å°†å˜æ›´ä¸ºâ€œä¸æŽ¥å—â€å¹¶ä¸”ä¸å¯ä½¿ç”¨ã€‚è¿™å¯èƒ½å¶å°”会å‘生,在å¦ä¸€ä¸ªèŠ‚点比你早几秒钟æˆåŠŸæŒ–出一个区å—时就会这样。</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation type="unfinished">调试信æ¯</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation type="unfinished">交易</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation type="unfinished">输入</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation type="unfinished">金é¢</translation>
+ </message>
+ <message>
+ <source>true</source>
+ <translation type="unfinished">是</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation type="unfinished">å¦</translation>
+ </message>
+</context>
+<context>
+ <name>TransactionDescDialog</name>
+ <message>
+ <source>This pane shows a detailed description of the transaction</source>
+ <translation type="unfinished">当å‰é¢æ¿æ˜¾ç¤ºäº†äº¤æ˜“的详细信æ¯</translation>
+ </message>
+ <message>
+ <source>Details for %1</source>
+ <translation type="unfinished">%1 详情</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation type="unfinished">日期</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation type="unfinished">类型</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">标签</translation>
</message>
<message>
+ <source>Unconfirmed</source>
+ <translation type="unfinished">未确认</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation type="unfinished">已丢弃</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation type="unfinished">确认中 (推è %2个确认,已ç»æœ‰ %1个确认)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation type="unfinished">已确认 (%1 个确认)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation type="unfinished">有冲çª</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation type="unfinished">未æˆç†Ÿ (%1 个确认,将在 %2 个åŽå¯ç”¨)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation type="unfinished">已生æˆä½†æœªè¢«æŽ¥å—</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation type="unfinished">接收到</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation type="unfinished">接收自</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation type="unfinished">å‘é€åˆ°</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation type="unfinished">支付给自己</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation type="unfinished">挖矿所得</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation type="unfinished">仅观察:</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation type="unfinished">(ä¸å¯ç”¨)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation type="unfinished">(无标签)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation type="unfinished">交易状æ€ã€‚ 鼠标移到此区域å¯æ˜¾ç¤ºç¡®è®¤æ•°ã€‚</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation type="unfinished">交易被接收的时间和日期。</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation type="unfinished">交易类型。</translation>
+ </message>
+ <message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation type="unfinished">该交易中是å¦æ¶‰åŠä»…观察地å€ã€‚</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation type="unfinished">用户自定义的该交易的æ„图/目的。</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation type="unfinished">从余é¢å¢žåŠ æˆ–移除的金é¢ã€‚</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation type="unfinished">全部</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation type="unfinished">今天</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation type="unfinished">本周</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation type="unfinished">本月</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation type="unfinished">上个月</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation type="unfinished">今年</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation type="unfinished">接收到</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation type="unfinished">å‘é€åˆ°</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation type="unfinished">给自己</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation type="unfinished">挖矿所得</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation type="unfinished">其它</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation type="unfinished">输入地å€ã€äº¤æ˜“ID或标签进行æœç´¢</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation type="unfinished">最å°é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>Range…</source>
+ <translation type="unfinished">范围...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">å¤åˆ¶åœ°å€(&amp;C)</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">å¤åˆ¶æ ‡ç­¾(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">å¤åˆ¶é‡‘é¢(&amp;A)</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">å¤åˆ¶äº¤æ˜“ &amp;ID</translation>
+ </message>
+ <message>
+ <source>Copy &amp;raw transaction</source>
+ <translation type="unfinished">å¤åˆ¶åŽŸå§‹äº¤æ˜“(&amp;R)</translation>
+ </message>
+ <message>
+ <source>Copy full transaction &amp;details</source>
+ <translation type="unfinished">å¤åˆ¶å®Œæ•´äº¤æ˜“详情(&amp;D)</translation>
+ </message>
+ <message>
+ <source>&amp;Show transaction details</source>
+ <translation type="unfinished">显示交易详情(&amp;S)</translation>
+ </message>
+ <message>
+ <source>Increase transaction &amp;fee</source>
+ <translation type="unfinished">增加矿工费(&amp;F)</translation>
+ </message>
+ <message>
+ <source>A&amp;bandon transaction</source>
+ <translation type="unfinished">放弃交易(&amp;B)</translation>
+ </message>
+ <message>
+ <source>&amp;Edit address label</source>
+ <translation type="unfinished">编辑地å€æ ‡ç­¾(&amp;E)</translation>
+ </message>
+ <message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">在 %1中显示</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation type="unfinished">导出交易历å²</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">逗å·åˆ†éš”文件</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation type="unfinished">已确认</translation>
+ </message>
+ <message>
+ <source>Watch-only</source>
+ <translation type="unfinished">仅观察</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation type="unfinished">日期</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation type="unfinished">类型</translation>
+ </message>
+ <message>
<source>Label</source>
<translation type="unfinished">标签</translation>
</message>
@@ -333,12 +4632,168 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Exporting Failed</source>
<translation type="unfinished">导出失败</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation type="unfinished">å°è¯•æŠŠäº¤æ˜“历å²ä¿å­˜åˆ° %1 æ—¶å‘生了错误。</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation type="unfinished">导出æˆåŠŸ</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation type="unfinished">å·²æˆåŠŸå°†äº¤æ˜“历å²ä¿å­˜åˆ° %1。</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation type="unfinished">范围:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation type="unfinished">到</translation>
+ </message>
+</context>
+<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation type="unfinished">未加载钱包。
+请转到“文件â€èœå• &gt; “打开钱包â€æ¥åŠ è½½ä¸€ä¸ªé’±åŒ…。
+- 或者 -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation type="unfinished">创建一个新的钱包</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">错误</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation type="unfinished">无法从剪贴æ¿è§£ç PSBT(Base64值无效)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation type="unfinished">加载交易数æ®</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation type="unfinished">部分签å交易 (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation type="unfinished">PSBT文件必须å°äºŽ100MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation type="unfinished">无法解ç PSBT</translation>
+ </message>
+</context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>Send Coins</source>
+ <translation type="unfinished">å‘å¸</translation>
+ </message>
+ <message>
+ <source>Fee bump error</source>
+ <translation type="unfinished">追加手续费出错</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation type="unfinished">追加交易手续费失败</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <extracomment>Asks a user if they would like to manually increase the fee of a transaction that has already been created.</extracomment>
+ <translation type="unfinished">您想追加手续费å—?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation type="unfinished">当å‰æ‰‹ç»­è´¹:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation type="unfinished">增加é‡:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation type="unfinished">新交易费:</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">警告: 因为在必è¦çš„时候会å‡å°‘找零输出个数或增加输入个数,这å¯èƒ½è¦ä»˜å‡ºé¢å¤–的费用。在没有找零输出的情况下å¯èƒ½ä¼šæ–°å¢žä¸€ä¸ªã€‚这些å˜æ›´å¯èƒ½ä¼šå¯¼è‡´æ½œåœ¨çš„éšç§æ³„露。</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation type="unfinished">确认手续费追加</translation>
+ </message>
+ <message>
+ <source>Can't draft transaction.</source>
+ <translation type="unfinished">无法起è‰äº¤æ˜“。</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation type="unfinished">å·²å¤åˆ¶PSBT</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation type="unfinished">无法签å交易</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation type="unfinished">无法æ交交易</translation>
+ </message>
+ <message>
+ <source>Can't display address</source>
+ <translation type="unfinished">无法显示地å€</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation type="unfinished">默认钱包</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">导出</translation>
+ <translation type="unfinished">导出(&amp;E)</translation>
</message>
- </context>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">将当å‰æ ‡ç­¾é¡µæ•°æ®å¯¼å‡ºåˆ°æ–‡ä»¶</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation type="unfinished">备份钱包</translation>
+ </message>
+ <message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">钱包数æ®</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation type="unfinished">备份失败</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation type="unfinished">å°è¯•ä¿å­˜é’±åŒ…æ•°æ®è‡³ %1 æ—¶å‘生了错误。</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation type="unfinished">备份æˆåŠŸ</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation type="unfinished">å·²æˆåŠŸä¿å­˜é’±åŒ…æ•°æ®è‡³ %1。</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation type="unfinished">å–消</translation>
+ </message>
+</context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_zh.ts b/src/qt/locale/bitcoin_zh.ts
index a91486f757..6feb5e9c84 100644
--- a/src/qt/locale/bitcoin_zh.ts
+++ b/src/qt/locale/bitcoin_zh.ts
@@ -1,6 +1,299 @@
<TS version="2.1" language="zh">
<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation type="unfinished">å³é”®å•å‡»æ¥ç¼–辑地å€æˆ–者标签</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation type="unfinished">创建新地å€</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation type="unfinished">新建(&amp;N)</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation type="unfinished">å¤åˆ¶å½“å‰é€‰ä¸­çš„地å€åˆ°ç³»ç»Ÿå‰ªè´´æ¿</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation type="unfinished">å¤åˆ¶(&amp;C)</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation type="unfinished">关闭(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation type="unfinished">从列表中删除当å‰å·²é€‰åœ°å€</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation type="unfinished">输入è¦æœç´¢çš„地å€æˆ–标签</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">将当å‰é€‰é¡¹å¡ä¸­çš„æ•°æ®å¯¼å‡ºåˆ°æ–‡ä»¶</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">导出(&amp;E)</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation type="unfinished">删除(&amp;D)</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation type="unfinished">选择收款人地å€</translation>
+ </message>
+ <message>
+ <source>Choose the address to receive coins with</source>
+ <translation type="unfinished">选择接收比特å¸åœ°å€</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation type="unfinished">选择(&amp;H)</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation type="unfinished">å‘é€åœ°å€</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation type="unfinished">接收地å€</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins.</source>
+ <translation type="unfinished">这些是你的比特å¸æ”¯ä»˜åœ°å€ã€‚在å‘é€ä¹‹å‰ï¼Œä¸€å®šè¦æ ¸å¯¹é‡‘é¢å’ŒæŽ¥æ”¶åœ°å€ã€‚</translation>
+ </message>
+ <message>
+ <source>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.
+Signing is only possible with addresses of the type 'legacy'.</source>
+ <translation type="unfinished">你将使用下列比特å¸åœ°å€æŽ¥å—付款。选å–收款选项å¡ä¸­ “产生新收款地å€â€ 按钮æ¥ç”Ÿæˆæ–°åœ°å€ã€‚
+ç­¾ååªèƒ½ä½¿ç”¨â€œä¼ ç»Ÿâ€ç±»åž‹çš„地å€ã€‚</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation type="unfinished">&amp;å¤åˆ¶åœ°å€</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation type="unfinished">å¤åˆ¶ &amp;标签</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation type="unfinished">&amp;编辑</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation type="unfinished">出å£åœ°å€åˆ—表</translation>
+ </message>
+ <message>
+ <source>Comma separated file</source>
+ <extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
+ <translation type="unfinished">逗å·åˆ†éš”文件</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the address list to %1. Please try again.</source>
+ <extracomment>An error message. %1 is a stand-in argument for the name of the file we attempted to save to.</extracomment>
+ <translation type="unfinished">试图将地å€åˆ—表ä¿å­˜åˆ° %1时出错,请å†è¯•ä¸€æ¬¡ã€‚</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation type="unfinished">导出失败</translation>
+ </message>
+</context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation type="unfinished">标签</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation type="unfinished">地å€</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation type="unfinished">(无标签)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Passphrase Dialog</source>
+ <translation type="unfinished">密ç å¯¹è¯æ¡†</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation type="unfinished">输入密ç </translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation type="unfinished">新的密ç </translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation type="unfinished">é‡å¤æ–°å¯†ç </translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation type="unfinished">显示密ç </translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation type="unfinished">加密钱包</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation type="unfinished">该æ“作需è¦æ‚¨çš„钱包密ç æ¥è§£é”钱包。</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation type="unfinished">打开钱包</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation type="unfinished">修改密ç </translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation type="unfinished">确认钱包加密</translation>
+ </message>
+ <message>
+ <source>Warning: If you encrypt your wallet and lose your passphrase, you will &lt;b&gt;LOSE ALL OF YOUR BITCOINS&lt;/b&gt;!</source>
+ <translation type="unfinished">注æ„: 如果你忘记了你的钱包,你将会丢失你的&lt;b&gt;密ç ï¼Œå¹¶ä¸”会丢失你的&lt;/b&gt;比特å¸ã€‚</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation type="unfinished">您确定è¦åŠ å¯†æ‚¨çš„钱包å—?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation type="unfinished">钱包加密</translation>
+ </message>
+ <message>
+ <source>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">输入钱包的新密ç ï¼Œ&lt;br/&gt;请使用&lt;b&gt;10个或以上éšæœºå­—符的密ç &lt;/b&gt;,&lt;b&gt;或者8个以上的å¤æ‚å•è¯&lt;/b&gt;。</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation type="unfinished">输入钱包的旧密ç å’Œæ–°å¯†ç ã€‚</translation>
+ </message>
+ <message>
+ <source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
+ <translation type="unfinished">注æ„,加密你的钱包并ä¸èƒ½å®Œå…¨ä¿æŠ¤ä½ çš„比特å¸å…å—感染你电脑的æ¶æ„软件的窃å–。</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation type="unfinished">加密钱包</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation type="unfinished">你的钱包è¦è¢«åŠ å¯†äº†ã€‚</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation type="unfinished">你的钱包现在被加密了。</translation>
+ </message>
+ <message>
+ <source>IMPORTANT: Any previous backups you have made of your wallet file should be replaced with the newly generated, encrypted wallet file. For security reasons, previous backups of the unencrypted wallet file will become useless as soon as you start using the new, encrypted wallet.</source>
+ <translation type="unfinished">é‡è¦æ示:您之å‰å¯¹é’±åŒ…文件所åšçš„任何备份都应该替æ¢ä¸ºæ–°ç”Ÿæˆçš„加密钱包文件。出于安全原因,一旦开始使用新的加密钱包,以å‰æœªåŠ å¯†é’±åŒ…文件的备份就会失效。</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation type="unfinished">钱包加密失败</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
+ <translation type="unfinished">由于内部错误,钱包加密失败。你的钱包没有加密æˆåŠŸã€‚</translation>
+ </message>
+ <message>
+ <source>The supplied passphrases do not match.</source>
+ <translation type="unfinished">æ供的密ç ä¸åŒ¹é…。</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation type="unfinished">钱包打开失败</translation>
+ </message>
+ <message>
+ <source>The passphrase entered for the wallet decryption was incorrect.</source>
+ <translation type="unfinished">钱包解密输入的密ç ä¸æ­£ç¡®ã€‚</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation type="unfinished">钱包密ç å·²æˆåŠŸæ›´æ”¹ã€‚</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation type="unfinished">警告:大写é”定键已打开!</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation type="unfinished">IP/å­ç½‘掩ç </translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation type="unfinished">被ç¦æ­¢ç›´åˆ°</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinApplication</name>
+ <message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">设置文件%1å¯èƒ½å·²æŸå或无效。</translation>
+ </message>
+ <message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">失控的例外</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation type="unfinished">å‘生了一个致命错误。%1ä¸èƒ½å†å®‰å…¨åœ°ç»§ç»­å¹¶å°†é€€å‡ºã€‚</translation>
+ </message>
+ <message>
+ <source>Internal error</source>
+ <translation type="unfinished">内部错误</translation>
+ </message>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">å‘生内部错误。%1å°†å°è¯•å®‰å…¨ç»§ç»­ã€‚这是一个æ„外的错误,å¯ä»¥æŠ¥å‘Šå¦‚下所述。</translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
+ <message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">è¦å°†è®¾ç½®é‡ç½®ä¸ºé»˜è®¤å€¼ï¼Œè¿˜æ˜¯ä¸åšä»»ä½•æ›´æ”¹å°±ä¸­æ­¢?</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">å‘生了一个致命错误。检查设置文件是å¦å¯å†™ï¼Œæˆ–者å°è¯•ä½¿ç”¨-nosettingsè¿è¡Œã€‚</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation type="unfinished">错误:指定的数æ®ç›®å½•â€œ%1“ä¸å­˜åœ¨ã€‚</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation type="unfinished">错误:无法解æžé…置文件:%1。</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation type="unfinished">错误: %1</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1尚未安全退出…</translation>
+ </message>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
@@ -39,8 +332,63 @@
</message>
</context>
<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">无法读å–设置文件</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">无法写入设置文件</translation>
+ </message>
+ </context>
+<context>
<name>BitcoinGUI</name>
<message>
+ <source>&amp;Overview</source>
+ <translation type="unfinished">&amp;概述</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation type="unfinished">显示钱包的总体概况</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation type="unfinished">&amp;交易</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation type="unfinished">æµè§ˆåŽ†å²äº¤æ˜“</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation type="unfinished">退&amp;出</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation type="unfinished">退出应用程åº</translation>
+ </message>
+ <message>
+ <source>&amp;About %1</source>
+ <translation type="unfinished">&amp;关于 %1</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation type="unfinished">显示信æ¯å…³äºŽ%1</translation>
+ </message>
+ <message>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation type="unfinished">加密您的钱包ç§é’¥</translation>
+ </message>
+ <message>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation type="unfinished">用您的比特å¸åœ°å€ç­¾åä¿¡æ¯ï¼Œä»¥è¯æ˜Žæ‹¥æœ‰å®ƒä»¬</translation>
+ </message>
+ <message>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation type="unfinished">验è¯æ¶ˆæ¯ï¼Œç¡®ä¿å®ƒä»¬æ˜¯ç”¨æŒ‡å®šçš„比特å¸åœ°å€ç­¾åçš„</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation type="unfinished">&amp;文件</translation>
</message>
@@ -176,19 +524,109 @@
<source>Copy amount</source>
<translation type="unfinished">å¤åˆ¶é‡‘é¢</translation>
</message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">å¤åˆ¶æ‰‹ç»­è´¹</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation type="unfinished">是</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation type="unfinished">当任何一个收款金é¢å°äºŽç›®å‰çš„粉尘金é¢é˜ˆå€¼æ—¶ï¼Œæ–‡å­—会å˜çº¢è‰²ã€‚</translation>
+ </message>
+ </context>
+<context>
+ <name>CreateWalletActivity</name>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">正在创建钱包&lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>Open Wallet</source>
+ <extracomment>Title of window indicating the progress of opening of a wallet.</extracomment>
+ <translation type="unfinished">打开钱包</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation type="unfinished">关闭钱包</translation>
+ </message>
+ </context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit sending address</source>
+ <translation type="unfinished">编辑付款地å€</translation>
+ </message>
</context>
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
<numerusform />
</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">错误</translation>
+ </message>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>&amp;Window</source>
+ <translation type="unfinished">&amp;窗å£</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">错误</translation>
+ </message>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>Node window</source>
+ <translation type="unfinished">结点窗å£</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
+ <message>
+ <source>Copy amount</source>
+ <translation type="unfinished">å¤åˆ¶é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation type="unfinished">å¤åˆ¶æ‰‹ç»­è´¹</translation>
+ </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -205,4 +643,22 @@
</translation>
</message>
</context>
+<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>Error</source>
+ <translation type="unfinished">错误</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation type="unfinished">&amp;导出</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation type="unfinished">将当å‰é€‰é¡¹å¡ä¸­çš„æ•°æ®å¯¼å‡ºåˆ°æ–‡ä»¶</translation>
+ </message>
+ </context>
</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts
index c4f84df359..e2e1f16c56 100644
--- a/src/qt/locale/bitcoin_zh_CN.ts
+++ b/src/qt/locale/bitcoin_zh_CN.ts
@@ -246,6 +246,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Settings file %1 might be corrupt or invalid.</source>
+ <translation type="unfinished">设置文件%1å¯èƒ½å·²æŸå或无效。</translation>
+ </message>
+ <message>
<source>Runaway exception</source>
<translation type="unfinished">未æ•èŽ·çš„异常</translation>
</message>
@@ -265,6 +269,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">è¦å°†è®¾ç½®é‡ç½®ä¸ºé»˜è®¤å€¼ï¼Œè¿˜æ˜¯è¦æ”¾å¼ƒæ›´æ”¹å¹¶ä¸­æ­¢ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">出现致命错误。请检查设置文件是å¦å¯å†™ï¼Œæˆ–者å°è¯•å¸¦ -nosettings å‚æ•°è¿è¡Œã€‚</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">错误:指定的数æ®ç›®å½•â€œ%1â€ä¸å­˜åœ¨ã€‚</translation>
</message>
@@ -366,31 +380,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n second(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n秒</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n minute(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n分钟</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n hour(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n å°æ—¶</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n day(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n 天</numerusform>
</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n 周</numerusform>
</translation>
</message>
<message>
@@ -400,7 +414,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>%n year(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%nå¹´</numerusform>
</translation>
</message>
<message>
@@ -411,6 +425,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">无法读å–设置文件</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">无法写入设置文件</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">%s å¼€å‘者</translation>
</message>
@@ -443,6 +465,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">è¯»å– %s æ—¶å‘生错误ï¼æ‰€æœ‰çš„密钥都å¯ä»¥æ­£ç¡®è¯»å–,但是交易记录或地å€ç°¿æ•°æ®å¯èƒ½å·²ç»ä¸¢å¤±æˆ–出错。</translation>
</message>
<message>
+ <source>Error reading %s! Transaction data may be missing or incorrect. Rescanning wallet.</source>
+ <translation type="unfinished">读å–%s出错ï¼äº¤æ˜“æ•°æ®å¯èƒ½ä¸¢å¤±æˆ–有误。é‡æ–°æ‰«æ钱包中。</translation>
+ </message>
+ <message>
<source>Error: Dumpfile format record is incorrect. Got "%s", expected "format".</source>
<translation type="unfinished">错误: 转储文件格å¼ä¸æ­£ç¡®ã€‚得到是"%s",而预期本应得到的是 "format"。</translation>
</message>
@@ -459,10 +485,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">错误: 传统钱包åªæ”¯æŒ "legacy", "p2sh-segwit", å’Œ "bech32" 这三ç§åœ°å€ç±»åž‹</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">错误:监å¬å¤–部连接失败 (listen函数返回了错误 %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">手续费估计失败。而且备用手续费估计(fallbackfee)已被ç¦ç”¨ã€‚请å†ç­‰ä¸€äº›åŒºå—,或者通过-fallbackfeeå‚æ•°å¯ç”¨å¤‡ç”¨æ‰‹ç»­è´¹ä¼°è®¡ã€‚</translation>
</message>
@@ -475,6 +497,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">å‚æ•° -maxtxfee=&lt;amount&gt;: '%s' 指定了éžæ³•çš„é‡‘é¢ (手续费必须至少达到最å°è½¬å‘费率(minrelay fee) %s 以é¿å…交易å¡ç€å‘ä¸å‡ºåŽ»)</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">无效或æŸåçš„peers.dat (%s)。如果你确信这是一个bug,请å馈到%s。作为å˜é€šåŠžæ³•ï¼Œä½ å¯ä»¥æŠŠçŽ°æœ‰æ–‡ä»¶ (%s) 移开(é‡å‘½åã€ç§»åŠ¨æˆ–删除),这样就å¯ä»¥åœ¨ä¸‹æ¬¡å¯åŠ¨æ—¶åˆ›å»ºä¸€ä¸ªæ–°æ–‡ä»¶äº†ã€‚</translation>
+ </message>
+ <message>
<source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
<translation type="unfinished">æ供多个洋葱路由绑定地å€ã€‚对自动创建的洋葱æœåŠ¡ç”¨%s</translation>
</message>
@@ -503,6 +529,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">修剪被设置得太å°ï¼Œå·²ç»ä½ŽäºŽæœ€å°å€¼%d MiB,请使用更大的数值。</translation>
</message>
<message>
+ <source>Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead.</source>
+ <translation type="unfinished">修剪模å¼ä¸Ž -reindex-chainstate ä¸å…¼å®¹ã€‚请进行一次完整的 -reindex 。</translation>
+ </message>
+ <message>
<source>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</source>
<translation type="unfinished">修剪:上次åŒæ­¥é’±åŒ…çš„ä½ç½®å·²ç»è¶…出(è½åŽäºŽï¼‰çŽ°æœ‰ä¿®å‰ªåŽæ•°æ®çš„范围。你需è¦è¿›è¡Œ-reindex(对于已ç»å¯ç”¨ä¿®å‰ªèŠ‚点,就需è¦é‡æ–°ä¸‹è½½æ•´ä¸ªåŒºå—链)</translation>
</message>
@@ -515,6 +545,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">区å—æ•°æ®åº“包å«æœªæ¥çš„交易,这å¯èƒ½æ˜¯ç”±æœ¬æœºé”™è¯¯çš„日期时间引起。若确认本机日期时间正确,请é‡æ–°å»ºç«‹åŒºå—æ•°æ®åº“。</translation>
</message>
<message>
+ <source>The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.</source>
+ <translation type="unfinished">区å—索引数æ®åº“å«æœ‰åŽ†å²é—留的 'txindex' 。å¯ä»¥è¿è¡Œå®Œæ•´çš„ -reindex æ¥æ¸…ç†è¢«å ç”¨çš„ç£ç›˜ç©ºé—´ï¼›ä¹Ÿå¯ä»¥å¿½ç•¥è¿™ä¸ªé”™è¯¯ã€‚这个错误消æ¯å°†ä¸ä¼šå†æ¬¡æ˜¾ç¤ºã€‚</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished">这笔交易在扣除手续费åŽçš„金é¢å¤ªå°ï¼Œä»¥è‡³äºŽæ— æ³•é€å‡º</translation>
</message>
@@ -551,6 +585,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">æä¾›äº†æœªçŸ¥çš„é’±åŒ…æ ¼å¼ "%s" 。请使用 "bdb" 或 "sqlite" 中的一ç§ã€‚</translation>
</message>
<message>
+ <source>Unsupported chainstate database format found. Please restart with -reindex-chainstate. This will rebuild the chainstate database.</source>
+ <translation type="unfinished">找到了ä¸å—支æŒçš„ chainstate æ•°æ®åº“æ ¼å¼ã€‚请使用 -reindex-chainstate å‚æ•°é‡å¯ã€‚这将会é‡å»º chainstate æ•°æ®åº“。</translation>
+ </message>
+ <message>
+ <source>Wallet created successfully. The legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future.</source>
+ <translation type="unfinished">钱包创建æˆåŠŸã€‚æ—§å¼é’±åŒ…已被弃用,未æ¥å°†ä¸å†æ”¯æŒåˆ›å»ºæˆ–打开旧å¼é’±åŒ…。</translation>
+ </message>
+ <message>
<source>Warning: Dumpfile wallet format "%s" does not match command line specified format "%s".</source>
<translation type="unfinished">警告: è½¬å‚¨æ–‡ä»¶çš„é’±åŒ…æ ¼å¼ "%s" ä¸Žå‘½ä»¤è¡ŒæŒ‡å®šçš„æ ¼å¼ "%s" ä¸ç¬¦ã€‚</translation>
</message>
@@ -587,6 +629,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">æ— æ³•è§£æž - %s 地å€: '%s'</translation>
</message>
<message>
+ <source>Cannot set -forcednsseed to true when setting -dnsseed to false.</source>
+ <translation type="unfinished">在 -dnsseed 被设为 false 时无法将 -forcednsseed 设为 true 。</translation>
+ </message>
+ <message>
<source>Cannot set -peerblockfilters without -blockfilterindex.</source>
<translation type="unfinished">没有å¯ç”¨-blockfilterindex,就ä¸èƒ½å¯ç”¨-peerblockfilters。</translation>
</message>
@@ -595,6 +641,98 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ä¸èƒ½å†™å…¥åˆ°æ•°æ®ç›®å½•'%s';请检查文件æƒé™ã€‚</translation>
</message>
<message>
+ <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">无法完æˆç”±ä¹‹å‰ç‰ˆæœ¬å¯åŠ¨çš„ -txindex å‡çº§ã€‚请用之å‰çš„版本é‡æ–°å¯åŠ¨ï¼Œæˆ–者进行一次完整的 -reindex 。</translation>
+ </message>
+ <message>
+ <source>%s request to listen on port %u. This port is considered "bad" and thus it is unlikely that any Bitcoin Core peers connect to it. See doc/p2p-bad-ports.md for details and a full list.</source>
+ <translation type="unfinished">%s请求监å¬ç«¯å£ %u。这个端å£è¢«è®¤ä¸ºæ˜¯â€œåçš„â€ï¼Œæ‰€ä»¥ä¸å¤ªå¯èƒ½æœ‰Bitcoin Core节点会连接到它。有关详细信æ¯å’Œå®Œæ•´åˆ—表,请å‚è§ doc/p2p-bad-ports.md 。</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -blockfilterindex. Please temporarily disable blockfilterindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate 与 -blockfilterindex ä¸å…¼å®¹ã€‚请在进行 -reindex-chainstate 时临时ç¦ç”¨ blockfilterindex ,或者改用 -reindex (而ä¸æ˜¯ -reindex-chainstate )æ¥å®Œæ•´åœ°é‡å»ºæ‰€æœ‰ç´¢å¼•ã€‚</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -coinstatsindex. Please temporarily disable coinstatsindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate 与 -coinstatsindex ä¸å…¼å®¹ã€‚请在进行 -reindex-chainstate 时临时ç¦ç”¨ coinstatsindex ,或者改用 -reindex (而ä¸æ˜¯ -reindex-chainstate )æ¥å®Œæ•´åœ°é‡å»ºæ‰€æœ‰ç´¢å¼•ã€‚</translation>
+ </message>
+ <message>
+ <source>-reindex-chainstate option is not compatible with -txindex. Please temporarily disable txindex while using -reindex-chainstate, or replace -reindex-chainstate with -reindex to fully rebuild all indexes.</source>
+ <translation type="unfinished">-reindex-chainstate 与 -txindex ä¸å…¼å®¹ã€‚请在进行 -reindex-chainstate 时临时ç¦ç”¨ txindex ,或者改用 -reindex (而ä¸æ˜¯ -reindex-chainstate )æ¥å®Œæ•´åœ°é‡å»ºæ‰€æœ‰ç´¢å¼•ã€‚</translation>
+ </message>
+ <message>
+ <source>Assumed-valid: last wallet synchronisation goes beyond available block data. You need to wait for the background validation chain to download more blocks.</source>
+ <translation type="unfinished">å‡å®šæœ‰æ•ˆï¼ˆassume-valid): 上次åŒæ­¥é’±åŒ…时进度越过了现有的区å—æ•°æ®ã€‚你需è¦ç­‰å¾…åŽå°éªŒè¯é“¾ä¸‹è½½æ›´å¤šçš„区å—。</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same time.</source>
+ <translation type="unfinished">在使用地å€ç®¡ç†å™¨(addrman)寻找出站连接时,无法åŒæ—¶æ供特定的连接。</translation>
+ </message>
+ <message>
+ <source>Error loading %s: External signer wallet being loaded without external signer support compiled</source>
+ <translation type="unfinished">加载%s时出错: 编译时未å¯ç”¨å¤–部签å器支æŒï¼Œå´ä»ç„¶è¯•å›¾åŠ è½½å¤–部签å器钱包</translation>
+ </message>
+ <message>
+ <source>Error: Address book data in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">错误:钱包中的地å€ç°¿æ•°æ®æ— æ³•è¢«è¯†åˆ«ä¸ºå±žäºŽè¿ç§»åŽçš„钱包</translation>
+ </message>
+ <message>
+ <source>Error: Duplicate descriptors created during migration. Your wallet may be corrupted.</source>
+ <translation type="unfinished">错误:è¿ç§»è¿‡ç¨‹ä¸­åˆ›å»ºäº†é‡å¤çš„输出æ述符。你的钱包å¯èƒ½å·²æŸå。</translation>
+ </message>
+ <message>
+ <source>Error: Transaction %s in wallet cannot be identified to belong to migrated wallets</source>
+ <translation type="unfinished">错误:钱包中的交易%s无法被识别为属于è¿ç§»åŽçš„钱包</translation>
+ </message>
+ <message>
+ <source>Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first</source>
+ <translation type="unfinished">错误:无法为这个é—留钱包生æˆè¾“出æ述符。请先确定钱包已被解é”</translation>
+ </message>
+ <message>
+ <source>Failed to rename invalid peers.dat file. Please move or delete it and try again.</source>
+ <translation type="unfinished">无法é‡å‘½å无效的 peers.dat 文件。 请移动或删除它,然åŽé‡è¯•ã€‚</translation>
+ </message>
+ <message>
+ <source>Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6</source>
+ <translation type="unfinished">互ä¸å…¼å®¹çš„选项:-dnsseed=1 已被显å¼æŒ‡å®šï¼Œä½† -onlynet ç¦æ­¢äº†IPv4/IPv6 连接</translation>
+ </message>
+ <message>
+ <source>Outbound connections restricted to Tor (-onlynet=onion) but the proxy for reaching the Tor network is explicitly forbidden: -onion=0</source>
+ <translation type="unfinished">出站连接被é™åˆ¶ä¸ºä»…使用 Tor (-onlynet=onion),但是到达 Tor 网络的代ç†è¢«æ˜¾å¼ç¦æ­¢ï¼š -onion=0</translation>
+ </message>
+ <message>
+ <source>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>
+ <translation type="unfinished">出站连接被é™åˆ¶ä¸ºä»…使用 Tor (-onlynet=onion),但是未æ供到达 Tor 网络的代ç†ï¼šæ²¡æœ‰æä¾› -proxy=, -onion= 或 -listenonion å‚æ•°</translation>
+ </message>
+ <message>
+ <source>Unrecognized descriptor found. Loading wallet %s
+
+The wallet might had been created on a newer version.
+Please try running the latest software version.
+</source>
+ <translation type="unfinished">找到无法识别的输出æ述符。加载钱包%s
+
+钱包å¯èƒ½ç”±æ–°ç‰ˆè½¯ä»¶åˆ›å»ºï¼Œ
+请å°è¯•è¿è¡Œæœ€æ–°çš„软件版本。
+</translation>
+ </message>
+ <message>
+ <source>Unsupported category-specific logging level -loglevel=%s. Expected -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s. Valid loglevels: %s.</source>
+ <translation type="unfinished">ä¸æ”¯æŒçš„类别é™å®šæ—¥å¿—等级 -loglevel=%s。预期å‚æ•° -loglevel=&lt;category&gt;:&lt;loglevel&gt;. Valid categories: %s。有效的类别: %s。</translation>
+ </message>
+ <message>
+ <source>
+Unable to cleanup failed migration</source>
+ <translation type="unfinished">
+无法清ç†å¤±è´¥çš„è¿ç§»</translation>
+ </message>
+ <message>
+ <source>
+Unable to restore backup of wallet.</source>
+ <translation type="unfinished">
+无法还原钱包备份</translation>
+ </message>
+ <message>
<source>Config setting for %s only applied on %s network when in [%s] section.</source>
<translation type="unfinished">对 %s çš„é…置设置åªå¯¹ %s 网络生效,如果它ä½äºŽé…置的 [%s] 章节的è¯ã€‚</translation>
</message>
@@ -675,8 +813,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">从钱包数æ®åº“读å–下一æ¡è®°å½•æ—¶å‡ºé”™</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">å‡çº§é“¾çŠ¶æ€(chainstate)æ•°æ®åº“出错</translation>
+ <source>Error: Could not add watchonly tx to watchonly wallet</source>
+ <translation type="unfinished">错误:无法添加仅观察交易至仅观察钱包</translation>
+ </message>
+ <message>
+ <source>Error: Could not delete watchonly transactions</source>
+ <translation type="unfinished">错误:无法删除仅观察交易</translation>
</message>
<message>
<source>Error: Couldn't create cursor into database</source>
@@ -691,6 +833,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">错误: 转储文件的校验和ä¸ç¬¦ã€‚计算得到%s,预料中本应该得到%s</translation>
</message>
<message>
+ <source>Error: Failed to create new watchonly wallet</source>
+ <translation type="unfinished">错误:创建新仅观察钱包失败</translation>
+ </message>
+ <message>
<source>Error: Got key that was not hex: %s</source>
<translation type="unfinished">错误: 得到了ä¸æ˜¯å六进制的键:%s</translation>
</message>
@@ -711,10 +857,38 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">错误: 没有å¯ç”¨çš„%s地å€ã€‚</translation>
</message>
<message>
+ <source>Error: Not all watchonly txs could be deleted</source>
+ <translation type="unfinished">错误:有些仅观察交易无法被删除</translation>
+ </message>
+ <message>
+ <source>Error: This wallet already uses SQLite</source>
+ <translation type="unfinished">错误:此钱包已ç»åœ¨ä½¿ç”¨SQLite</translation>
+ </message>
+ <message>
+ <source>Error: This wallet is already a descriptor wallet</source>
+ <translation type="unfinished">错误:这个钱包已ç»æ˜¯è¾“出æ述符钱包</translation>
+ </message>
+ <message>
+ <source>Error: Unable to begin reading all records in the database</source>
+ <translation type="unfinished">错误:无法开始读å–这个数æ®åº“中的所有记录</translation>
+ </message>
+ <message>
+ <source>Error: Unable to make a backup of your wallet</source>
+ <translation type="unfinished">错误:无法为你的钱包创建备份</translation>
+ </message>
+ <message>
<source>Error: Unable to parse version %u as a uint32_t</source>
<translation type="unfinished">错误:无法把版本å·%u作为unit32_t解æž</translation>
</message>
<message>
+ <source>Error: Unable to read all records in the database</source>
+ <translation type="unfinished">错误:无法读å–这个数æ®åº“中的所有记录</translation>
+ </message>
+ <message>
+ <source>Error: Unable to remove watchonly address book data</source>
+ <translation type="unfinished">错误:无法移除仅观察地å€ç°¿æ•°æ®</translation>
+ </message>
+ <message>
<source>Error: Unable to write record to new wallet</source>
<translation type="unfinished">错误: 无法写入记录到新钱包</translation>
</message>
@@ -751,6 +925,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">åˆå§‹åŒ–完整性检查失败。%s å³å°†å…³é—­ã€‚</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">找ä¸åˆ°äº¤æ˜“输入项,å¯èƒ½å·²ç»è¢«èŠ±æŽ‰äº†</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">金é¢ä¸è¶³</translation>
</message>
@@ -791,6 +969,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">å‚æ•° -whitelist: '%s' 指定了无效的网络掩ç </translation>
</message>
<message>
+ <source>Listening for incoming connections failed (listen returned error %s)</source>
+ <translation type="unfinished">监å¬å¤–部连接失败 (listen函数返回了错误 %s)</translation>
+ </message>
+ <message>
<source>Loading P2P addresses…</source>
<translation type="unfinished">加载P2P地å€...</translation>
</message>
@@ -807,12 +989,20 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">加载钱包...</translation>
</message>
<message>
+ <source>Missing amount</source>
+ <translation type="unfinished">找ä¸åˆ°é‡‘é¢</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">找ä¸åˆ°ç”¨äºŽä¼°è®¡äº¤æ˜“大å°çš„解答数æ®</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">-whitebind: '%s' 需è¦æŒ‡å®šä¸€ä¸ªç«¯å£</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">未指定代ç†æœåŠ¡å™¨ã€‚请使用 -proxy=&lt;ip&gt; 或 -proxy=&lt;ip:port&gt; 。</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">没有å¯ç”¨çš„地å€</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -823,10 +1013,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ä¸èƒ½æŠŠä¿®å‰ªé…ç½®æˆä¸€ä¸ªè´Ÿæ•°ã€‚</translation>
</message>
<message>
- <source>Prune mode is incompatible with -coinstatsindex.</source>
- <translation type="unfinished">区å—修剪模å¼ä¸Ž coinstatsindex ä¸å…¼å®¹ã€‚</translation>
- </message>
- <message>
<source>Prune mode is incompatible with -txindex.</source>
<translation type="unfinished">修剪模å¼ä¸Ž -txindex ä¸å…¼å®¹ã€‚</translation>
</message>
@@ -927,6 +1113,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">交易金é¢ä¸ä¸å¯ä¸ºè´Ÿæ•°</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">交易找零输出项编å·è¶…出范围</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">此交易在内存池中的存在过长的链æ¡</translation>
</message>
@@ -935,10 +1125,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">交易必须包å«è‡³å°‘一个收款人</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">交易需è¦ä¸€ä¸ªæ‰¾é›¶åœ°å€ï¼Œä½†æ˜¯æˆ‘们无法生æˆå®ƒã€‚</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">交易过大</translation>
</message>
<message>
+ <source>Unable to allocate memory for -maxsigcachesize: '%s' MiB</source>
+ <translation type="unfinished">无法为 -maxsigcachesize: '%s' MiB 分é…内存</translation>
+ </message>
+ <message>
<source>Unable to bind to %s on this computer (bind returned error %s)</source>
<translation type="unfinished">无法在本机绑定%sç«¯å£ (bind函数返回了错误 %s)</translation>
</message>
@@ -951,6 +1149,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">无法创建PID文件'%s': %s</translation>
</message>
<message>
+ <source>Unable to find UTXO for external input</source>
+ <translation type="unfinished">无法为外部输入找到UTXO</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation type="unfinished">无法生æˆåˆå§‹å¯†é’¥</translation>
</message>
@@ -963,10 +1165,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">无法打开%s用于写入</translation>
</message>
<message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">æ— æ³•è§£æž -maxuploadtarget: '%s'</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">无法å¯åŠ¨HTTPæœåŠ¡ï¼ŒæŸ¥çœ‹æ—¥å¿—获å–更多信æ¯</translation>
</message>
<message>
+ <source>Unable to unload the wallet before migrating</source>
+ <translation type="unfinished">在è¿ç§»å‰æ— æ³•å¸è½½é’±åŒ…</translation>
+ </message>
+ <message>
<source>Unknown -blockfilterindex value %s.</source>
<translation type="unfinished">未知的 -blockfilterindex 数值 %s。</translation>
</message>
@@ -987,12 +1197,12 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ä¸æ˜Žçš„交易规则已ç»æ¿€æ´» (versionbit %i)</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">ä¸æ”¯æŒçš„日志分类 %s=%s。</translation>
+ <source>Unsupported global logging level -loglevel=%s. Valid values: %s.</source>
+ <translation type="unfinished">ä¸æ”¯æŒçš„全局日志等级 -loglevel=%s 。有效的数值:%s 。</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">正在å‡çº§UTXOæ•°æ®åº“</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">ä¸æ”¯æŒçš„日志分类 %s=%s。</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
@@ -1062,6 +1272,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">创建一个新的钱包</translation>
</message>
<message>
+ <source>&amp;Minimize</source>
+ <translation type="unfinished">最å°åŒ–(&amp;M)</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation type="unfinished">钱包:</translation>
</message>
@@ -1209,7 +1423,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<message numerus="yes">
<source>Processed %n block(s) of transaction history.</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>已处ç†%n个区å—的交易历å²ã€‚</numerusform>
</translation>
</message>
<message>
@@ -1249,6 +1463,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">加载部分签å比特å¸äº¤æ˜“(PSBT)</translation>
</message>
<message>
+ <source>Load PSBT from &amp;clipboard…</source>
+ <translation type="unfinished">从剪贴æ¿åŠ è½½PSBT(&amp;C)...</translation>
+ </message>
+ <message>
<source>Load Partially Signed Bitcoin Transaction from clipboard</source>
<translation type="unfinished">从剪贴æ¿ä¸­åŠ è½½éƒ¨åˆ†ç­¾å比特å¸äº¤æ˜“(PSBT)</translation>
</message>
@@ -1285,6 +1503,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">å¸è½½é’±åŒ…</translation>
</message>
<message>
+ <source>Restore Wallet…</source>
+ <extracomment>Name of the menu item that restores wallet from a backup file.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…...</translation>
+ </message>
+ <message>
+ <source>Restore a wallet from a backup file</source>
+ <extracomment>Status tip for Restore Wallet menu item</extracomment>
+ <translation type="unfinished">从备份文件æ¢å¤é’±åŒ…</translation>
+ </message>
+ <message>
<source>Close all wallets</source>
<translation type="unfinished">关闭所有钱包</translation>
</message>
@@ -1309,6 +1537,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">没有å¯ç”¨çš„钱包</translation>
</message>
<message>
+ <source>Wallet Data</source>
+ <extracomment>Name of the wallet data file format.</extracomment>
+ <translation type="unfinished">钱包数æ®</translation>
+ </message>
+ <message>
+ <source>Load Wallet Backup</source>
+ <extracomment>The title for Restore Wallet File Windows</extracomment>
+ <translation type="unfinished">加载钱包备份</translation>
+ </message>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of pop-up window shown when the user is attempting to restore a wallet.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">钱包å称</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation type="unfinished">窗å£(&amp;W)</translation>
</message>
@@ -1324,11 +1572,19 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 客户端</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">éšè—(&amp;H)</translation>
+ </message>
+ <message>
+ <source>S&amp;how</source>
+ <translation type="unfinished">显示(&amp;H)</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>%n æ¡åˆ°æ¯”特å¸ç½‘络的活动连接</numerusform>
</translation>
</message>
<message>
@@ -1352,6 +1608,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">å¯ç”¨ç½‘络活动</translation>
</message>
<message>
+ <source>Pre-syncing Headers (%1%)…</source>
+ <translation type="unfinished">预åŒæ­¥åŒºå—头 (%1%)…</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">错误: %1</translation>
</message>
@@ -1522,6 +1782,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">å¤åˆ¶é‡‘é¢(&amp;A)</translation>
</message>
<message>
+ <source>Copy transaction &amp;ID and output index</source>
+ <translation type="unfinished">å¤åˆ¶äº¤æ˜“&amp;ID和输出åºå·</translation>
+ </message>
+ <message>
<source>L&amp;ock unspent</source>
<translation type="unfinished">é”定未花费(&amp;O)</translation>
</message>
@@ -1610,6 +1874,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Can't list signers</source>
<translation type="unfinished">无法列出签å器</translation>
</message>
+ <message>
+ <source>Too many external signers found</source>
+ <translation type="unfinished">找到的外部签å器太多</translation>
+ </message>
+</context>
+<context>
+ <name>LoadWalletsActivity</name>
+ <message>
+ <source>Load Wallets</source>
+ <extracomment>Title of progress window which is displayed when wallets are being loaded.</extracomment>
+ <translation type="unfinished">加载钱包</translation>
+ </message>
+ <message>
+ <source>Loading wallets…</source>
+ <extracomment>Descriptive text of the load wallets progress window which indicates to the user that wallets are currently being loaded.</extracomment>
+ <translation type="unfinished">加载钱包...</translation>
+ </message>
</context>
<context>
<name>OpenWalletActivity</name>
@@ -1637,6 +1918,34 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>RestoreWalletActivity</name>
+ <message>
+ <source>Restore Wallet</source>
+ <extracomment>Title of progress window which is displayed when wallets are being restored.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…</translation>
+ </message>
+ <message>
+ <source>Restoring Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the restore wallets progress window which indicates to the user that wallets are currently being restored.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…&lt;b&gt;%1&lt;/b&gt;…</translation>
+ </message>
+ <message>
+ <source>Restore wallet failed</source>
+ <extracomment>Title of message box which is displayed when the wallet could not be restored.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…失败</translation>
+ </message>
+ <message>
+ <source>Restore wallet warning</source>
+ <extracomment>Title of message box which is displayed when the wallet is restored with some warning.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…警告</translation>
+ </message>
+ <message>
+ <source>Restore wallet message</source>
+ <extracomment>Title of message box which is displayed when the wallet is successfully restored.</extracomment>
+ <translation type="unfinished">æ¢å¤é’±åŒ…消æ¯</translation>
+ </message>
+</context>
+<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
@@ -1815,13 +2124,23 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Bitcoin</source>
<translation type="unfinished">比特å¸</translation>
</message>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(éœ€è¦ %1 GB)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform>å¯ç”¨ç©ºé—´ %n GB</numerusform>
+ </translation>
</message>
- <message>
- <source>(%1 GB needed for full chain)</source>
- <translation type="unfinished">(完整区å—é“¾éœ€è¦ %1 GB)</translation>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform>(éœ€è¦ %n GB的空间)</numerusform>
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform>(ä¿å­˜å®Œæ•´çš„é“¾éœ€è¦ %n GB)</numerusform>
+ </translation>
</message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
@@ -1835,7 +2154,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
- <numerusform />
+ <numerusform>(足以æ¢å¤ %n 天之内的备份)</numerusform>
</translation>
</message>
<message>
@@ -1867,10 +2186,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">由于这是第一次å¯åŠ¨æ­¤ç¨‹åºï¼Œæ‚¨å¯ä»¥é€‰æ‹©%1存储数æ®çš„ä½ç½®</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">当你å•å‡»ç¡®è®¤åŽï¼Œ%1 将会在 %4 å¯åŠ¨æ—¶ä»Ž %3 中最早的交易开始,下载并处ç†å®Œæ•´çš„ %4 区å—链 (%2GB)。</translation>
- </message>
- <message>
<source>Limit block chain storage to</source>
<translation type="unfinished">将区å—链存储é™åˆ¶åˆ°</translation>
</message>
@@ -1883,6 +2198,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">åˆå§‹åŒ–åŒæ­¥è¿‡ç¨‹æ˜¯éžå¸¸åƒåŠ›çš„,åŒæ—¶å¯èƒ½ä¼šæš´éœ²æ‚¨ä¹‹å‰æ²¡æœ‰æ³¨æ„到的电脑硬件问题。你æ¯æ¬¡å¯åŠ¨%1时,它都会从之å‰ä¸­æ–­çš„地方继续下载。</translation>
</message>
<message>
+ <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2 GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
+ <translation type="unfinished">当你å•å‡»ç¡®è®¤åŽï¼Œ%1 将会从%4在%3年创始时最早的交易开始,下载并处ç†å®Œæ•´çš„ %4 区å—链 (%2 GB)。</translation>
+ </message>
+ <message>
<source>If you have chosen to limit block chain storage (pruning), the historical data must still be downloaded and processed, but will be deleted afterward to keep your disk usage low.</source>
<translation type="unfinished">如果你选择é™åˆ¶åŒºå—链存储大å°ï¼ˆåŒºå—链è£å‰ªæ¨¡å¼ï¼‰ï¼Œç¨‹åºä¾ç„¶ä¼šä¸‹è½½å¹¶å¤„ç†å…¨éƒ¨åŽ†å²æ•°æ®ï¼Œåªæ˜¯ä¸å¿…须的部分会在使用åŽè¢«åˆ é™¤ï¼Œä»¥å ç”¨æœ€å°‘的存储空间。</translation>
</message>
@@ -1975,6 +2294,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>Unknown. Syncing Headers (%1, %2%)…</source>
<translation type="unfinished">未知。åŒæ­¥åŒºå—头(%1, %2%)...</translation>
</message>
+ <message>
+ <source>Unknown. Pre-syncing Headers (%1, %2%)…</source>
+ <translation type="unfinished">未知。预åŒæ­¥åŒºå—头 (%1, %2%)…</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -2031,6 +2354,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">窗å£è¢«å…³é—­æ—¶æœ€å°åŒ–程åºè€Œä¸æ˜¯é€€å‡ºã€‚当此选项å¯ç”¨æ—¶ï¼Œåªæœ‰åœ¨èœå•ä¸­é€‰æ‹©â€œé€€å‡ºâ€æ—¶æ‰ä¼šè®©ç¨‹åºé€€å‡ºã€‚</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line:</source>
+ <translation type="unfinished">这个对è¯æ¡†ä¸­çš„设置已被如下命令行选项覆盖:</translation>
+ </message>
+ <message>
<source>Open the %1 configuration file from the working directory.</source>
<translation type="unfinished">从工作目录下打开é…置文件 %1。</translation>
</message>
@@ -2059,14 +2386,44 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">警告:还原此设置需è¦é‡æ–°ä¸‹è½½æ•´ä¸ªåŒºå—链。</translation>
</message>
<message>
+ <source>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>
+ <extracomment>Tooltip text for Options window setting that sets the size of the database cache. Explains the corresponding effects of increasing/decreasing this value.</extracomment>
+ <translation type="unfinished">æ•°æ®åº“缓存的最大大å°ã€‚加大缓存有助于加快åŒæ­¥ï¼Œä½†å¯¹äºŽå¤§å¤šæ•°ä½¿ç”¨åœºæ™¯æ¥è¯´ï¼Œç»§ç»­åŠ å¤§åŽæ”¶æ•ˆä¼šè¶Šæ¥è¶Šä¸æ˜Žæ˜¾ã€‚é™ä½Žç¼“存大å°å°†ä¼šå‡å°å†…存使用é‡ã€‚内存池中尚未被使用的那部分内存也会被共享用于这里的数æ®åº“缓存。</translation>
+ </message>
+ <message>
+ <source>Set the number of script verification threads. Negative values correspond to the number of cores you want to leave free to the system.</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">设置脚本验è¯çº¿ç¨‹çš„æ•°é‡ã€‚负值则表示你想è¦ä¿ç•™ç»™ç³»ç»Ÿçš„核心数é‡ã€‚</translation>
+ </message>
+ <message>
<source>(0 = auto, &lt;0 = leave that many cores free)</source>
<translation type="unfinished">(0 = 自动, &lt;0 = ä¿æŒæŒ‡å®šæ•°é‡çš„CPU核心空闲)</translation>
</message>
<message>
+ <source>This allows you or a third party tool to communicate with the node through command-line and JSON-RPC commands.</source>
+ <extracomment>Tooltip text for Options window setting that enables the RPC server.</extracomment>
+ <translation type="unfinished">è¿™å…许作为用户的你或第三方工具通过命令行和JSON-RPC命令行与节点通信。</translation>
+ </message>
+ <message>
+ <source>Enable R&amp;PC server</source>
+ <extracomment>An Options window setting to enable the RPC server.</extracomment>
+ <translation type="unfinished">å¯ç”¨R&amp;PCæœåŠ¡å™¨</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation type="unfinished">钱包(&amp;A)</translation>
</message>
<message>
+ <source>Whether to set subtract fee from amount as default or not.</source>
+ <extracomment>Tooltip text for Options window setting that sets subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">是å¦è¦é»˜è®¤ä»Žé‡‘é¢ä¸­å‡åŽ»æ‰‹ç»­è´¹ã€‚</translation>
+ </message>
+ <message>
+ <source>Subtract &amp;fee from amount by default</source>
+ <extracomment>An Options window setting to set subtracting the fee from a sending amount as default.</extracomment>
+ <translation type="unfinished">默认从金é¢ä¸­å‡åŽ»äº¤æ˜“手续费(&amp;F)</translation>
+ </message>
+ <message>
<source>Expert</source>
<translation type="unfinished">专家</translation>
</message>
@@ -2083,6 +2440,16 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">动用尚未确认的找零资金(&amp;S)</translation>
</message>
<message>
+ <source>Enable &amp;PSBT controls</source>
+ <extracomment>An options window setting to enable PSBT controls.</extracomment>
+ <translation type="unfinished">å¯ç”¨&amp;PSBT控件</translation>
+ </message>
+ <message>
+ <source>Whether to show PSBT controls.</source>
+ <extracomment>Tooltip text for options window setting that enables PSBT controls.</extracomment>
+ <translation type="unfinished">是å¦è¦æ˜¾ç¤ºPSBT控件</translation>
+ </message>
+ <message>
<source>External Signer (e.g. hardware wallet)</source>
<translation type="unfinished">外部签å器(例如硬件钱包)</translation>
</message>
@@ -2187,6 +2554,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">选择显示åŠå‘é€æ¯”特å¸æ—¶ä½¿ç”¨çš„最å°å•ä½ã€‚</translation>
</message>
<message>
+ <source>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>
+ <translation type="unfinished">这个第三方网å€ï¼ˆæ¯”如区å—æµè§ˆå™¨ï¼‰ä¼šå‡ºçŽ°åœ¨äº¤æ˜“选项å¡çš„å³é”®èœå•ä¸­ã€‚ 网å€ä¸­çš„%s代表交易哈希。多个网å€éœ€è¦ç”¨ç«–线 | 相互分隔。</translation>
+ </message>
+ <message>
+ <source>&amp;Third-party transaction URLs</source>
+ <translation type="unfinished">第三方交易网å€(&amp;T)</translation>
+ </message>
+ <message>
<source>Whether to show coin control features or not.</source>
<translation type="unfinished">是å¦æ˜¾ç¤ºæ‰‹åŠ¨é€‰å¸åŠŸèƒ½ã€‚</translation>
</message>
@@ -2211,10 +2586,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">与 "%1" 最接近的匹é…</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">这个对è¯æ¡†ä¸­çš„设置已被如下命令行选项或é…置文件项覆盖:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">确定(&amp;O)</translation>
</message>
@@ -2237,14 +2608,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">确认æ¢å¤é»˜è®¤è®¾ç½®</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">需è¦é‡å¯å®¢æˆ·ç«¯æ‰èƒ½ä½¿æ›´æ”¹ç”Ÿæ•ˆã€‚</translation>
</message>
<message>
+ <source>Current settings will be backed up at "%1".</source>
+ <extracomment>Text explaining to the user that the client's current settings will be backed up at a specific location. %1 is a stand-in argument for the backup location's path.</extracomment>
+ <translation type="unfinished">当å‰è®¾ç½®å°†ä¼šè¢«å¤‡ä»½åˆ° "%1"。</translation>
+ </message>
+ <message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">客户端å³å°†å…³é—­ï¼Œæ‚¨æƒ³ç»§ç»­å—?</translation>
</message>
<message>
@@ -2258,6 +2637,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">é…置文件å¯ä»¥ç”¨æ¥è®¾ç½®é«˜çº§é€‰é¡¹ã€‚é…置文件会覆盖设置界é¢çª—å£ä¸­çš„选项。此外,命令行会覆盖é…置文件指定的选项。</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">继续</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">å–消</translation>
</message>
@@ -2279,6 +2662,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
</context>
<context>
+ <name>OptionsModel</name>
+ <message>
+ <source>Could not read setting "%1", %2.</source>
+ <translation type="unfinished">无法读å–设置 "%1",%2。</translation>
+ </message>
+</context>
+<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
@@ -2392,6 +2782,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">ç­¾å交易失败: %1</translation>
</message>
<message>
+ <source>Cannot sign inputs while wallet is locked.</source>
+ <translation type="unfinished">钱包已é”定,无法签å交易输入项。</translation>
+ </message>
+ <message>
<source>Could not sign any more inputs.</source>
<translation type="unfinished">没有交易输入项å¯ä¾›ç­¾å了。</translation>
</message>
@@ -2465,6 +2859,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">交易ä»ç„¶éœ€è¦ç­¾å。</translation>
</message>
<message>
+ <source>(But no wallet is loaded.)</source>
+ <translation type="unfinished">(但没有加载钱包。)</translation>
+ </message>
+ <message>
<source>(But this wallet cannot sign transactions.)</source>
<translation type="unfinished">(但这个钱包ä¸èƒ½ç­¾å交易)</translation>
</message>
@@ -2529,6 +2927,11 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">节点</translation>
</message>
<message>
+ <source>Age</source>
+ <extracomment>Title of Peers Table column which indicates the duration (length of time) since the peer connection started.</extracomment>
+ <translation type="unfinished">连接时间</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">æ–¹å‘</translation>
@@ -2716,6 +3119,10 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">å·²åŒæ­¥åŒºå—</translation>
</message>
<message>
+ <source>Last Transaction</source>
+ <translation type="unfinished">最近交易</translation>
+ </message>
+ <message>
<source>The mapped Autonomous System used for diversifying peer selection.</source>
<translation type="unfinished">映射到的自治系统,被用æ¥å¤šæ ·åŒ–选择节点</translation>
</message>
@@ -2724,6 +3131,36 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">映射到的AS</translation>
</message>
<message>
+ <source>Whether we relay addresses to this peer.</source>
+ <extracomment>Tooltip text for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">是å¦æŠŠåœ°å€è½¬å‘给这个节点。</translation>
+ </message>
+ <message>
+ <source>Address Relay</source>
+ <extracomment>Text title for the Address Relay field in the peer details area, which displays whether we relay addresses to this peer (Yes/No).</extracomment>
+ <translation type="unfinished">地å€è½¬å‘</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</source>
+ <extracomment>Tooltip text for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">从这个节点接收并处ç†è¿‡çš„地å€æ€»æ•°ï¼ˆé™¤åŽ»å› é¢‘次é™åˆ¶è€Œä¸¢å¼ƒçš„那些地å€ï¼‰ã€‚</translation>
+ </message>
+ <message>
+ <source>The total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</source>
+ <extracomment>Tooltip text for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">从这个节点接收åŽåˆå› é¢‘次é™åˆ¶è€Œä¸¢å¼ƒï¼ˆæœªè¢«å¤„ç†ï¼‰çš„地å€æ€»æ•°ã€‚</translation>
+ </message>
+ <message>
+ <source>Addresses Processed</source>
+ <extracomment>Text title for the Addresses Processed field in the peer details area, which displays the total number of addresses received from this peer that were processed (excludes addresses that were dropped due to rate-limiting).</extracomment>
+ <translation type="unfinished">已处ç†åœ°å€</translation>
+ </message>
+ <message>
+ <source>Addresses Rate-Limited</source>
+ <extracomment>Text title for the Addresses Rate-Limited field in the peer details area, which displays the total number of addresses received from this peer that were dropped (not processed) due to rate-limiting.</extracomment>
+ <translation type="unfinished">被频率é™åˆ¶ä¸¢å¼ƒçš„地å€</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation type="unfinished">用户代ç†</translation>
</message>
@@ -2932,6 +3369,11 @@ If you are receiving this error you should request the merchant provide a BIP21
<translation type="unfinished">1 å¹´(&amp;Y)</translation>
</message>
<message>
+ <source>&amp;Copy IP/Netmask</source>
+ <extracomment>Context menu action to copy the IP/Netmask of a banned peer. IP/Netmask is the combination of a peer's IP address and its Netmask. For IP address, see: https://en.wikipedia.org/wiki/IP_address.</extracomment>
+ <translation type="unfinished">å¤åˆ¶IP/网络掩ç (&amp;C)</translation>
+ </message>
+ <message>
<source>&amp;Unban</source>
<translation type="unfinished">解å°(&amp;U)</translation>
</message>
@@ -3460,6 +3902,16 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">请务必仔细检查您的交易请求。这会产生一个部分签å比特å¸äº¤æ˜“(PSBT),å¯ä»¥æŠŠä¿å­˜ä¸‹æ¥æˆ–å¤åˆ¶å‡ºåŽ»ï¼Œç„¶åŽå°±å¯ä»¥å¯¹å®ƒè¿›è¡Œç­¾å,比如用离线%1钱包,或是用兼容PSBT的硬件钱包。</translation>
</message>
<message>
+ <source>Do you want to create this transaction?</source>
+ <extracomment>Message displayed when attempting to create a transaction. Cautionary text to prompt the user to verify that the displayed transaction details represent the transaction the user intends to create.</extracomment>
+ <translation type="unfinished">è¦åˆ›å»ºè¿™ç¬”交易å—?</translation>
+ </message>
+ <message>
+ <source>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>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">请务必仔细检查您的交易。你å¯ä»¥åˆ›å»ºå¹¶å‘é€è¿™ç¬”交易;也å¯ä»¥åˆ›å»ºä¸€ä¸ªâ€œéƒ¨åˆ†ç­¾å比特å¸äº¤æ˜“(PSBT)â€ï¼Œå®ƒå¯ä»¥è¢«ä¿å­˜ä¸‹æ¥æˆ–被å¤åˆ¶å‡ºåŽ»ï¼Œç„¶åŽå°±å¯ä»¥å¯¹å®ƒè¿›è¡Œç­¾å,比如用离线%1钱包,或是用兼容PSBT的硬件钱包。</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<extracomment>Text to prompt a user to review the details of the transaction they are attempting to send.</extracomment>
<translation type="unfinished">请检查您的交易。</translation>
@@ -3512,14 +3964,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">超过 %1 的手续费被视为高得离谱。</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">支付请求已过期。</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>预计%n个区å—内确认。</numerusform>
</translation>
</message>
<message>
@@ -3594,14 +4042,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">消æ¯:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">这是一个未ç»éªŒè¯çš„支付请求。</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">这是一个已ç»éªŒè¯çš„支付请求。</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">请为此地å€è¾“入一个标签以将它加入已用地å€åˆ—表</translation>
</message>
@@ -3609,14 +4049,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">bitcoin: URI 附带的备注信æ¯ï¼Œå°†ä¼šå’Œäº¤æ˜“一起存储,备查。 注æ„:该消æ¯ä¸ä¼šé€šè¿‡æ¯”特å¸ç½‘络传输。</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">支付给:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">附言:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3689,7 +4121,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
</message>
<message>
<source>Enter the receiver's address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack. Note that this only proves the signing party receives with the address, it cannot prove sendership of any transaction!</source>
- <translation type="unfinished">请在下é¢è¾“入接收者地å€ã€æ¶ˆæ¯ï¼ˆç¡®ä¿æ¢è¡Œç¬¦ã€ç©ºæ ¼ç¬¦ã€åˆ¶è¡¨ç¬¦ç­‰å®Œå…¨ç›¸åŒï¼‰å’Œç­¾å以验è¯æ¶ˆæ¯ã€‚请仔细核对签åä¿¡æ¯ï¼Œä»¥æ防中间人攻击。请注æ„,这åªæ˜¯è¯æ˜ŽæŽ¥æ”¶æ–¹å¯ä»¥ç”¨è¿™ä¸ªåœ°å€ç­¾å,它ä¸èƒ½è¯æ˜Žä»»ä½•äº¤æ˜“ï¼</translation>
+ <translation type="unfinished">请在下é¢è¾“入接收者地å€ã€æ¶ˆæ¯ï¼ˆç¡®ä¿æ¢è¡Œç¬¦ã€ç©ºæ ¼ç¬¦ã€åˆ¶è¡¨ç¬¦ç­‰å®Œå…¨ç›¸åŒï¼‰å’Œç­¾å以验è¯æ¶ˆæ¯ã€‚请仔细核对签åä¿¡æ¯ï¼Œä»¥æ防中间人攻击。请注æ„,这åªæ˜¯è¯æ˜ŽæŽ¥æ”¶æ–¹å¯ä»¥ç”¨è¿™ä¸ªåœ°å€ç­¾å,它ä¸èƒ½è¯æ˜Žä»»ä½•äº¤æ˜“çš„å‘é€äººèº«ä»½ï¼</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
@@ -3778,35 +4210,41 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<source>(press q to shutdown and continue later)</source>
<translation type="unfinished">(按q退出并在以åŽç»§ç»­)</translation>
</message>
- </context>
+ <message>
+ <source>press q to shutdown</source>
+ <translation type="unfinished">按q键关闭并退出</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">与一个有 %1 个确认的交易冲çª</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0/未确认,%1</translation>
+ <source>0/unconfirmed, in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is in the memory pool.</extracomment>
+ <translation type="unfinished">0/未确认,在内存池中</translation>
</message>
<message>
- <source>in memory pool</source>
- <translation type="unfinished">在内存池中</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ä¸åœ¨å†…存池中</translation>
+ <source>0/unconfirmed, not in memory pool</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that is not in the memory pool.</extracomment>
+ <translation type="unfinished">0/未确认,ä¸åœ¨å†…存池中</translation>
</message>
<message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">已丢弃</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1/未确认</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">%1 个确认</translation>
</message>
<message>
@@ -3856,7 +4294,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<message numerus="yes">
<source>matures in %n more block(s)</source>
<translation type="unfinished">
- <numerusform />
+ <numerusform>在%n个区å—内æˆç†Ÿ</numerusform>
</translation>
</message>
<message>
@@ -4153,6 +4591,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee rate of "100 satos
<translation type="unfinished">编辑地å€æ ‡ç­¾(&amp;E)</translation>
</message>
<message>
+ <source>Show in %1</source>
+ <extracomment>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.</extracomment>
+ <translation type="unfinished">在 %1中显示</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">导出交易历å²</translation>
</message>
diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts
index eff1971a9c..b6b5c2fe8c 100644
--- a/src/qt/locale/bitcoin_zh_HK.ts
+++ b/src/qt/locale/bitcoin_zh_HK.ts
@@ -499,6 +499,24 @@
<context>
<name>Intro</name>
<message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
<extracomment>Explanatory text on the capability of the current prune target.</extracomment>
<translation type="unfinished">
diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts
index 229e1ce8ce..c05fd424a8 100644
--- a/src/qt/locale/bitcoin_zh_TW.ts
+++ b/src/qt/locale/bitcoin_zh_TW.ts
@@ -35,7 +35,7 @@
</message>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">匯出(&amp;E)</translation>
+ <translation type="unfinished">&amp;匯出</translation>
</message>
<message>
<source>&amp;Delete</source>
@@ -168,7 +168,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<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">輸入錢包的新密碼短語。&lt;br/&gt;請使用&lt;b&gt;個或10個以上隨機字符&lt;/b&gt;或&lt;b&gt;個8個以上單詞3的密碼。</translation>
+ <translation type="unfinished">輸入錢包的新密碼短語。&lt;br/&gt;請使用&lt;b&gt;個或10個以上隨機字符&lt;/b&gt;或&lt;b&gt;個8個以上單詞&lt;/b&gt;的密碼。</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
@@ -237,13 +237,31 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>BitcoinApplication</name>
<message>
+ <source>Runaway exception</source>
+ <translation type="unfinished">失控異常</translation>
+ </message>
+ <message>
<source>Internal error</source>
<translation type="unfinished">內部錯誤</translation>
</message>
- </context>
+ <message>
+ <source>An internal error occurred. %1 will attempt to continue safely. This is an unexpected bug which can be reported as described below.</source>
+ <translation type="unfinished">發生了內部錯誤%1 將嘗試安全地繼續。 這是一個æ„外錯誤,å¯ä»¥æŒ‰å¦‚下所述進行報告。</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
+ <source>Do you want to reset settings to default values, or to abort without making changes?</source>
+ <extracomment>Explanatory text shown on startup when the settings file cannot be read. Prompts user to make a choice between resetting or aborting.</extracomment>
+ <translation type="unfinished">您想將設置é‡ç½®ç‚ºé è¨­å€¼ï¼Œé‚„是在ä¸é€²è¡Œæ›´æ”¹çš„情æ³ä¸‹ä¸­æ­¢ï¼Ÿ</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. Check that settings file is writable, or try running with -nosettings.</source>
+ <extracomment>Explanatory text shown on startup when the settings file could not be written. Prompts user to check that we have the ability to write to the file. Explains that the user has the option of running without a settings file.</extracomment>
+ <translation type="unfinished">發生致命錯誤。檢查設置文件是å¦å¯å¯«å…¥ï¼Œæˆ–嘗試é‹è¡Œ -nosettings</translation>
+ </message>
+ <message>
<source>Error: Specified data directory "%1" does not exist.</source>
<translation type="unfinished">错误:指定的数æ®ç›®å½•â€œ%1â€ä¸å­˜åœ¨ã€‚</translation>
</message>
@@ -256,6 +274,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">错误:%1</translation>
</message>
<message>
+ <source>%1 didn't yet exit safely…</source>
+ <translation type="unfinished">%1還沒有安全退出……</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation type="unfinished">未知</translation>
</message>
@@ -268,6 +290,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">輸入 æ¯”ç‰¹å¹£åœ°å€ (比如說 %1)</translation>
</message>
<message>
+ <source>Unroutable</source>
+ <translation type="unfinished">ä¸å¯è·¯ç”±</translation>
+ </message>
+ <message>
<source>Inbound</source>
<extracomment>An inbound connection from a peer. An inbound connection is a connection initiated by a peer.</extracomment>
<translation type="unfinished">進來</translation>
@@ -361,6 +387,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Settings file could not be read</source>
+ <translation type="unfinished">設定檔案無法讀å–</translation>
+ </message>
+ <message>
+ <source>Settings file could not be written</source>
+ <translation type="unfinished">設定檔案無法寫入</translation>
+ </message>
+ <message>
<source>The %s developers</source>
<translation type="unfinished">%s 開發人員</translation>
</message>
@@ -381,10 +415,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">讀å–錢包檔 %s 時發生錯誤ï¼æ‰€æœ‰çš„鑰匙都正確讀å–了,但是交易資料或地å€ç°¿è³‡æ–™å¯èƒ½æœƒç¼ºå°‘或ä¸æ­£ç¢ºã€‚</translation>
</message>
<message>
- <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation type="unfinished">錯誤: è½å€™å¤–來連線失敗(回傳錯誤 %s)</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished">計算é ä¼°æ‰‹çºŒè²»å¤±æ•—了,也沒有備用手續費(fallbackfee)å¯ç”¨ã€‚è«‹å†å¤šç­‰å¾…幾個å€å¡Šï¼Œæˆ–是啟用 -fallbackfee åƒæ•¸ã€‚</translation>
</message>
@@ -541,10 +571,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">讀å–資料庫時發生錯誤,è¦é—œé–‰äº†ã€‚</translation>
</message>
<message>
- <source>Error upgrading chainstate database</source>
- <translation type="unfinished">å‡ç´šå€å¡Šéˆç‹€æ…‹è³‡æ–™åº«æ™‚發生錯誤</translation>
- </message>
- <message>
<source>Error: Disk space is low for %s</source>
<translation type="unfinished">错误: %s 所在的ç£ç›˜ç©ºé—´ä½Žã€‚</translation>
</message>
@@ -561,6 +587,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">åˆå§‹åŒ–時é‡æ–°æŽƒæ錢包失敗了</translation>
</message>
<message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation type="unfinished">手續費費率(%s) 低於最低費率設置(%s)</translation>
+ </message>
+ <message>
+ <source>Importing…</source>
+ <translation type="unfinished">匯入中...</translation>
+ </message>
+ <message>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
<translation type="unfinished">創世å€å¡Šä¸æ­£ç¢ºæˆ–找ä¸åˆ°ã€‚資料目錄錯了嗎?</translation>
</message>
@@ -569,6 +603,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">åˆå§‹åŒ–時的基本檢查失敗了。%s å°±è¦é—œé–‰äº†ã€‚</translation>
</message>
<message>
+ <source>Input not found or already spent</source>
+ <translation type="unfinished">找ä¸åˆ°äº¤æ˜“項,或å¯èƒ½å·²ç¶“花掉了</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation type="unfinished">ç´¯ç©é‡‘é¡ä¸è¶³</translation>
</message>
@@ -586,31 +624,55 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation type="unfinished">åƒæ•¸ -%s=&lt;金é¡&gt; 指定的金é¡ç„¡æ•ˆ: '%s'</translation>
+ <translation type="unfinished">無效金é¡çµ¦ -%s=&lt;amount&gt;:'%s'</translation>
</message>
<message>
<source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation type="unfinished">設定 -discardfee=&lt;金é¡&gt; 的金é¡ç„¡æ•ˆ: '%s'</translation>
+ <translation type="unfinished">無效金é¡çµ¦ -丟棄費=&lt;amount&gt;; '%s' </translation>
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation type="unfinished">設定 -fallbackfee=&lt;金é¡&gt; 的金é¡ç„¡æ•ˆ: '%s'</translation>
+ <translation type="unfinished">無效金é¡çµ¦ -後備費用=&lt;amount&gt;: '%s'</translation>
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation type="unfinished">設定 -paytxfee=&lt;金é¡&gt; 的金é¡ç„¡æ•ˆ: '%s' (至少è¦æœ‰ %s)</translation>
+ <translation type="unfinished">無效金é¡çµ¦ -支付費用&lt;amount&gt;:'%s' (必須至少%s)</translation>
</message>
<message>
<source>Invalid netmask specified in -whitelist: '%s'</source>
<translation type="unfinished">指定在 -whitelist 的網段無效: '%s'</translation>
</message>
<message>
+ <source>Loading P2P addresses…</source>
+ <translation type="unfinished">載入P2P地å€ä¸­...</translation>
+ </message>
+ <message>
+ <source>Loading banlist…</source>
+ <translation type="unfinished">正在載入黑å單中...</translation>
+ </message>
+ <message>
+ <source>Loading block index…</source>
+ <translation type="unfinished">載入å€å¡Šç´¢å¼•ä¸­...</translation>
+ </message>
+ <message>
+ <source>Loading wallet…</source>
+ <translation type="unfinished">載入錢包中...</translation>
+ </message>
+ <message>
+ <source>Missing amount</source>
+ <translation type="unfinished">缺少金é¡</translation>
+ </message>
+ <message>
+ <source>Missing solving data for estimating transaction size</source>
+ <translation type="unfinished">缺少用於估計交易è¦æ¨¡çš„求解數據</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation type="unfinished">指定 -whitebind 時必須包å«é€šè¨ŠåŸ : '%s'</translation>
</message>
<message>
- <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
- <translation type="unfinished">未指定代ç†ä¼ºæœå™¨ã€‚使用-proxy = &lt;ip&gt;或-proxy = &lt;ip:port&gt;。</translation>
+ <source>No addresses available</source>
+ <translation type="unfinished">沒有å¯ç”¨çš„地å€</translation>
</message>
<message>
<source>Not enough file descriptors available.</source>
@@ -625,10 +687,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">修剪模å¼å’Œ -txindex åƒæ•¸ä¸ç›¸å®¹ã€‚</translation>
</message>
<message>
+ <source>Pruning blockstore…</source>
+ <translation type="unfinished">修剪å€å¡Šè³‡æ–™åº«ä¸­...</translation>
+ </message>
+ <message>
<source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
<translation type="unfinished">因為系統的é™åˆ¶ï¼Œå°‡ -maxconnections åƒæ•¸å¾ž %d é™åˆ°äº† %d</translation>
</message>
<message>
+ <source>Replaying blocks…</source>
+ <translation type="unfinished">正在å°å€å¡Šé€²è¡Œé‡æ–°è¨ˆç®—...</translation>
+ </message>
+ <message>
+ <source>Rescanning…</source>
+ <translation type="unfinished">é‡æ–°æŽƒæ中...</translation>
+ </message>
+ <message>
<source>Section [%s] is not recognized.</source>
<translation type="unfinished">无法识别é…置章节 [%s]。</translation>
</message>
@@ -653,10 +727,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">指定的å€å¡Šç›®éŒ„ "%s" ä¸å­˜åœ¨ã€‚</translation>
</message>
<message>
+ <source>Starting network threads…</source>
+ <translation type="unfinished">正在開始網路線程...</translation>
+ </message>
+ <message>
<source>The source code is available from %s.</source>
<translation type="unfinished">原始碼å¯ä»¥åœ¨ %s å–得。</translation>
</message>
<message>
+ <source>The specified config file %s does not exist</source>
+ <translation type="unfinished">這個指定的é…置檔案%sä¸å­˜åœ¨</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to pay the fee</source>
<translation type="unfinished">交易金é¡å¤ªå°‘而付ä¸èµ·æ‰‹çºŒè²»</translation>
</message>
@@ -685,6 +767,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">交易金é¡ä¸èƒ½æ˜¯è² çš„</translation>
</message>
<message>
+ <source>Transaction change output index out of range</source>
+ <translation type="unfinished">交易尋找零輸出項超出範åœ</translation>
+ </message>
+ <message>
<source>Transaction has too long of a mempool chain</source>
<translation type="unfinished">交易造æˆè¨˜æ†¶æ± ä¸­çš„交易éˆå¤ªé•·</translation>
</message>
@@ -693,6 +779,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">交易必須至少有一個收款人</translation>
</message>
<message>
+ <source>Transaction needs a change address, but we can't generate it.</source>
+ <translation type="unfinished">需è¦äº¤æ˜“一個找零地å€ï¼Œä½†æ˜¯æˆ‘們無法生æˆå®ƒã€‚</translation>
+ </message>
+ <message>
<source>Transaction too large</source>
<translation type="unfinished">交易ä½å…ƒé‡å¤ªå¤§</translation>
</message>
@@ -717,6 +807,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">沒辦法產生密鑰</translation>
</message>
<message>
+ <source>Unable to open %s for writing</source>
+ <translation type="unfinished">無法開啟%s來寫入</translation>
+ </message>
+ <message>
+ <source>Unable to parse -maxuploadtarget: '%s'</source>
+ <translation type="unfinished">無法解æž-最大上傳目標:'%s'</translation>
+ </message>
+ <message>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished">無法啟動 HTTP 伺æœå™¨ã€‚詳情請看除錯紀錄。</translation>
</message>
@@ -737,18 +835,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">在 -onlynet 指定了ä¸æ˜Žçš„網路別: '%s'</translation>
</message>
<message>
- <source>Unsupported logging category %s=%s.</source>
- <translation type="unfinished">ä¸æ”¯æ´çš„紀錄類別 %s=%s。</translation>
+ <source>Unknown new rules activated (versionbit %i)</source>
+ <translation type="unfinished">未知的交易已經有新è¦å‰‡æ¿€æ´» (versionbit %i)</translation>
</message>
<message>
- <source>Upgrading UTXO database</source>
- <translation type="unfinished">正在å‡ç´š UTXO 資料庫</translation>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation type="unfinished">ä¸æ”¯æ´çš„紀錄類別 %s=%s。</translation>
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
<translation type="unfinished">使用者代ç†è¨»è§£(%s)中å«æœ‰ä¸å®‰å…¨çš„字元。</translation>
</message>
<message>
+ <source>Verifying blocks…</source>
+ <translation type="unfinished">正在驗證å€å¡Šæ•¸æ“š...</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)…</source>
+ <translation type="unfinished">正在驗證錢包...</translation>
+ </message>
+ <message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
<translation type="unfinished">錢包需è¦é‡å¯«: è«‹é‡æ–°å•“å‹• %s 來完æˆ</translation>
</message>
@@ -829,18 +935,63 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">&amp;接收</translation>
</message>
<message>
+ <source>&amp;Options…</source>
+ <translation type="unfinished">&amp;é¸é …...</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet…</source>
+ <translation type="unfinished">&amp;加密錢包...</translation>
+ </message>
+ <message>
<source>Encrypt the private keys that belong to your wallet</source>
<translation type="unfinished">將錢包中之密鑰加密</translation>
</message>
<message>
+ <source>&amp;Backup Wallet…</source>
+ <translation type="unfinished">&amp;備用錢包</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase…</source>
+ <translation type="unfinished">&amp;更改密碼短語...</translation>
+ </message>
+ <message>
+ <source>Sign &amp;message…</source>
+ <translation type="unfinished">ç°½å &amp;ä¿¡æ¯â€¦</translation>
+ </message>
+ <message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
<translation type="unfinished">用比特幣地å€ç°½å訊æ¯ä¾†è­‰æ˜Žä½å€æ˜¯ä½ çš„</translation>
</message>
<message>
+ <source>&amp;Verify message…</source>
+ <translation type="unfinished">&amp;é©—è­‰
+訊æ¯...</translation>
+ </message>
+ <message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
<translation type="unfinished">驗證訊æ¯æ˜¯ç”¨ä¾†ç¢ºå®šè¨Šæ¯æ˜¯ç”¨æŒ‡å®šçš„比特幣地å€ç°½åçš„</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file…</source>
+ <translation type="unfinished">&amp;從檔案載入PSBT...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI…</source>
+ <translation type="unfinished">é–‹å•Ÿ &amp;URI...</translation>
+ </message>
+ <message>
+ <source>Close Wallet…</source>
+ <translation type="unfinished">关钱包...</translation>
+ </message>
+ <message>
+ <source>Create Wallet…</source>
+ <translation type="unfinished">创建钱包...</translation>
+ </message>
+ <message>
+ <source>Close All Wallets…</source>
+ <translation type="unfinished">关所有钱包...</translation>
+ </message>
+ <message>
<source>&amp;File</source>
<translation type="unfinished">&amp;檔案</translation>
</message>
@@ -857,6 +1008,30 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">分é å·¥å…·åˆ—</translation>
</message>
<message>
+ <source>Syncing Headers (%1%)…</source>
+ <translation type="unfinished">åŒæ­¥å€å¡Šé ­ (%1%)…</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network…</source>
+ <translation type="unfinished">正在與網絡åŒæ­¥â€¦</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk…</source>
+ <translation type="unfinished">索引ç£ç›¤ä¸Šçš„索引塊中...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk…</source>
+ <translation type="unfinished">處ç†ç£ç¢Ÿè£¡çš„å€å¡Šä¸­...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk…</source>
+ <translation type="unfinished">正在é‡æ–°ç´¢å¼•ç£ç›¤ä¸Šçš„å€å¡Š...</translation>
+ </message>
+ <message>
+ <source>Connecting to peers…</source>
+ <translation type="unfinished">连到åŒè¡Œ...</translation>
+ </message>
+ <message>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished">è¦æ±‚付款(產生 QR Code å’Œ bitcoin 付款å”議的資æºè­˜åˆ¥ç¢¼: URI)</translation>
</message>
@@ -883,6 +1058,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">è½å¾Œ %1</translation>
</message>
<message>
+ <source>Catching up…</source>
+ <translation type="unfinished">赶上...</translation>
+ </message>
+ <message>
<source>Last received block was generated %1 ago.</source>
<translation type="unfinished">最近收到的å€å¡Šæ˜¯åœ¨ %1 以å‰ç”Ÿå‡ºä¾†çš„。</translation>
</message>
@@ -971,8 +1150,13 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">没有å¯ç”¨çš„钱包</translation>
</message>
<message>
+ <source>Wallet Name</source>
+ <extracomment>Label of the input field where the name of the wallet is entered.</extracomment>
+ <translation type="unfinished">錢包å稱</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
- <translation type="unfinished">視窗(&amp;W)</translation>
+ <translation type="unfinished">&amp;視窗</translation>
</message>
<message>
<source>Zoom</source>
@@ -986,6 +1170,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>%1 client</source>
<translation type="unfinished">%1 客戶端</translation>
</message>
+ <message>
+ <source>&amp;Hide</source>
+ <translation type="unfinished">&amp;躲</translation>
+ </message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network.</source>
<extracomment>A substring of the tooltip.</extracomment>
@@ -994,6 +1182,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</translation>
</message>
<message>
+ <source>Click for more actions.</source>
+ <extracomment>A substring of the tooltip. "More actions" are available via the context menu.</extracomment>
+ <translation type="unfinished">點擊查看更多æ“作</translation>
+ </message>
+ <message>
+ <source>Show Peers tab</source>
+ <extracomment>A context menu item. The "Peers tab" is an element of the "Node window".</extracomment>
+ <translation type="unfinished">顯示節點é¸é …å¡</translation>
+ </message>
+ <message>
+ <source>Disable network activity</source>
+ <extracomment>A context menu item.</extracomment>
+ <translation type="unfinished">關閉網路紀錄</translation>
+ </message>
+ <message>
+ <source>Enable network activity</source>
+ <extracomment>A context menu item. The network activity was disabled previously.</extracomment>
+ <translation type="unfinished">關閉網路紀錄</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation type="unfinished">错误:%1</translation>
</message>
@@ -1152,6 +1360,26 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">複製金é¡</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;å¤åˆ¶åœ°å€</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">å¤åˆ¶å’Œæ ‡ç­¾</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">å¤åˆ¶å’Œæ•°é‡</translation>
+ </message>
+ <message>
+ <source>L&amp;ock unspent</source>
+ <translation type="unfinished">鎖定未消費金é¡é¡</translation>
+ </message>
+ <message>
+ <source>&amp;Unlock unspent</source>
+ <translation type="unfinished">解鎖未花費金é¡</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation type="unfinished">複製數目</translation>
</message>
@@ -1216,6 +1444,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">新增錢包</translation>
</message>
<message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;…</source>
+ <extracomment>Descriptive text of the create wallet progress window which indicates to the user which wallet is currently being created.</extracomment>
+ <translation type="unfinished">正在創建錢包&lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
<source>Create wallet failed</source>
<translation type="unfinished">創建錢包失敗&lt;br&gt;</translation>
</message>
@@ -1394,6 +1627,24 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</context>
<context>
<name>Intro</name>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ </translation>
+ </message>
<message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation type="unfinished">在這個目錄中至少會存放 %1 GB 的資料,並且還會隨時間增加。</translation>
@@ -1438,10 +1689,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">因為這是程å¼ç¬¬ä¸€æ¬¡å•“動,你å¯ä»¥é¸æ“‡ %1 儲存資料的地方。</translation>
</message>
<message>
- <source>When you click OK, %1 will begin to download and process the full %4 block chain (%2GB) starting with the earliest transactions in %3 when %4 initially launched.</source>
- <translation type="unfinished">在你按下「好ã€ä¹‹å¾Œï¼Œ%1 就會開始下載並處ç†æ•´å€‹ %4 å€å¡Šéˆ(大å°æ˜¯ %2GB),也就是從 %3 å¹´ %4 剛剛起步時的最åˆäº¤æ˜“開始。</translation>
- </message>
- <message>
<source>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>
<translation type="unfinished">還原此設置需è¦é‡æ–°ä¸‹è¼‰æ•´å€‹å€å¡Šéˆã€‚首先下載完整的éˆï¼Œç„¶å¾Œå†ä¿®å‰ªå®ƒæ˜¯æ›´å¿«çš„。ç¦ç”¨æŸäº›é«˜ç´šåŠŸèƒ½ã€‚</translation>
</message>
@@ -1503,6 +1750,14 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">剩餘å€å¡Šæ•¸</translation>
</message>
<message>
+ <source>Unknown…</source>
+ <translation type="unfinished">ä¸æ˜Ž...</translation>
+ </message>
+ <message>
+ <source>calculating…</source>
+ <translation type="unfinished">计算...</translation>
+ </message>
+ <message>
<source>Last block time</source>
<translation type="unfinished">最近å€å¡Šæ™‚é–“</translation>
</message>
@@ -1675,7 +1930,7 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>&amp;Window</source>
- <translation type="unfinished">視窗(&amp;W)</translation>
+ <translation type="unfinished">&amp;視窗</translation>
</message>
<message>
<source>Show only a tray icon after minimizing the window.</source>
@@ -1722,10 +1977,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">使用個別的SOCKS&5代ç†ä»‹ç”±Tor onionæœå‹™åˆ°é”peers:</translation>
</message>
<message>
- <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
- <translation type="unfinished">这个对è¯æ¡†ä¸­çš„设置已被如下命令行选项或é…置文件项覆盖:</translation>
- </message>
- <message>
<source>&amp;OK</source>
<translation type="unfinished">好(&amp;O)</translation>
</message>
@@ -1743,14 +1994,17 @@ Signing is only possible with addresses of the type 'legacy'.</source>
</message>
<message>
<source>Confirm options reset</source>
+ <extracomment>Window title text of pop-up window shown when the user has chosen to reset options.</extracomment>
<translation type="unfinished">確èªé‡è¨­é¸é …</translation>
</message>
<message>
<source>Client restart required to activate changes.</source>
+ <extracomment>Text explaining that the settings changed will not come into effect until the client is restarted.</extracomment>
<translation type="unfinished">需è¦é‡æ–°é–‹å§‹å®¢æˆ¶ç«¯è»Ÿé«”來讓改變生效。</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
+ <extracomment>Text asking the user to confirm if they would like to proceed with a client shutdown.</extracomment>
<translation type="unfinished">客戶端軟體就è¦é—œæŽ‰äº†ã€‚繼續åšä¸‹åŽ»å—Žï¼Ÿ</translation>
</message>
<message>
@@ -1764,6 +2018,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">設定檔å¯ä»¥ç”¨ä¾†æŒ‡å®šé€²éšŽçš„使用é¸é …,並且會覆蓋掉圖形介é¢çš„設定。ä¸éŽï¼Œå‘½ä»¤åˆ—çš„é¸é …也會覆蓋掉設定檔中的é¸é …。</translation>
</message>
<message>
+ <source>Continue</source>
+ <translation type="unfinished">继续</translation>
+ </message>
+ <message>
<source>Cancel</source>
<translation type="unfinished">å–消</translation>
</message>
@@ -1882,6 +2140,10 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">複製到剪貼簿</translation>
</message>
<message>
+ <source>Save…</source>
+ <translation type="unfinished">拯救...</translation>
+ </message>
+ <message>
<source>Close</source>
<translation type="unfinished">關閉</translation>
</message>
@@ -1990,6 +2252,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">Ping 時間</translation>
</message>
<message>
+ <source>Peer</source>
+ <extracomment>Title of Peers Table column which contains a unique number used to identify a connection.</extracomment>
+ <translation type="unfinished">åŒè¡Œ</translation>
+ </message>
+ <message>
<source>Direction</source>
<extracomment>Title of Peers Table column which indicates the direction the peer connection was initiated from.</extracomment>
<translation type="unfinished">æ–¹å‘</translation>
@@ -2276,6 +2543,11 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">去:</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <extracomment>Context menu action to copy the address of a peer.</extracomment>
+ <translation type="unfinished">&amp;å¤åˆ¶åœ°å€</translation>
+ </message>
+ <message>
<source>&amp;Disconnect</source>
<translation type="unfinished">æ–·ç·š(&amp;D)</translation>
</message>
@@ -2411,6 +2683,18 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">複製 &amp;URI</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;å¤åˆ¶åœ°å€</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">å¤åˆ¶å’Œæ ‡ç­¾</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">å¤åˆ¶å’Œæ•°é‡</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation type="unfinished">沒辦法把錢包解鎖。</translation>
</message>
@@ -2740,10 +3024,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
<translation type="unfinished">高於 %1 的手續費會被èªç‚ºæ˜¯ä¸åˆç†ã€‚</translation>
</message>
- <message>
- <source>Payment request expired.</source>
- <translation type="unfinished">付款的è¦æ±‚éŽæœŸäº†ã€‚</translation>
- </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
@@ -2822,14 +3102,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">訊æ¯:</translation>
</message>
<message>
- <source>This is an unauthenticated payment request.</source>
- <translation type="unfinished">這是個沒有驗證éŽèº«ä»½çš„付款è¦æ±‚。</translation>
- </message>
- <message>
- <source>This is an authenticated payment request.</source>
- <translation type="unfinished">這是個已經驗證éŽèº«ä»½çš„付款è¦æ±‚。</translation>
- </message>
- <message>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished">請輸入這個地å€çš„標籤,來把它加進去已使用éŽåœ°å€æ¸…單。</translation>
</message>
@@ -2837,14 +3109,6 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<source>A message that was attached to the bitcoin: URI which will be stored with the transaction for your reference. Note: This message will not be sent over the Bitcoin network.</source>
<translation type="unfinished">附加在 Bitcoin 付款å”議的資æºè­˜åˆ¥ç¢¼(URI)中的訊æ¯ï¼Œæœƒå’Œäº¤æ˜“內容一起存起來,給你自己åšåƒè€ƒã€‚注æ„: 這個訊æ¯ä¸æœƒé€åˆ° Bitcoin 網路上。</translation>
</message>
- <message>
- <source>Pay To:</source>
- <translation type="unfinished">付給:</translation>
- </message>
- <message>
- <source>Memo:</source>
- <translation type="unfinished">備註:</translation>
- </message>
</context>
<context>
<name>SendConfirmationDialog</name>
@@ -3011,30 +3275,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<name>TransactionDesc</name>
<message>
<source>conflicted with a transaction with %1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an unconfirmed transaction that conflicts with a confirmed transaction.</extracomment>
<translation type="unfinished">跟一個目å‰ç¢ºèª %1 次的交易互相è¡çª</translation>
</message>
<message>
- <source>0/unconfirmed, %1</source>
- <translation type="unfinished">0 次/未確èªï¼Œ%1</translation>
- </message>
- <message>
- <source>in memory pool</source>
- <translation type="unfinished">在記憶池中</translation>
- </message>
- <message>
- <source>not in memory pool</source>
- <translation type="unfinished">ä¸åœ¨è¨˜æ†¶æ± ä¸­</translation>
- </message>
- <message>
<source>abandoned</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents an abandoned transaction.</extracomment>
<translation type="unfinished">已中止</translation>
</message>
<message>
<source>%1/unconfirmed</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in at least one block, but less than 6 blocks.</extracomment>
<translation type="unfinished">%1 次/未確èª</translation>
</message>
<message>
<source>%1 confirmations</source>
+ <extracomment>Text explaining the current status of a transaction, shown in the status field of the details window for this transaction. This status represents a transaction confirmed in 6 or more blocks.</extracomment>
<translation type="unfinished">ç¢ºèª %1 次</translation>
</message>
<message>
@@ -3337,6 +3593,22 @@ Signing is only possible with addresses of the type 'legacy'.</source>
<translation type="unfinished">最å°é‡‘é¡</translation>
</message>
<message>
+ <source>&amp;Copy address</source>
+ <translation type="unfinished">&amp;å¤åˆ¶åœ°å€</translation>
+ </message>
+ <message>
+ <source>Copy &amp;label</source>
+ <translation type="unfinished">å¤åˆ¶å’Œæ ‡ç­¾</translation>
+ </message>
+ <message>
+ <source>Copy &amp;amount</source>
+ <translation type="unfinished">å¤åˆ¶å’Œæ•°é‡</translation>
+ </message>
+ <message>
+ <source>Copy transaction &amp;ID</source>
+ <translation type="unfinished">複製交易 &amp;ID</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation type="unfinished">匯出交易記錄</translation>
</message>
@@ -3497,7 +3769,7 @@ Go to File &gt; Open Wallet to load a wallet.
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation type="unfinished">匯出(&amp;E)</translation>
+ <translation type="unfinished">&amp;匯出</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
diff --git a/src/qt/locale/bitcoin_zu.ts b/src/qt/locale/bitcoin_zu.ts
index bcae817b16..0f6155b046 100644
--- a/src/qt/locale/bitcoin_zu.ts
+++ b/src/qt/locale/bitcoin_zu.ts
@@ -2,6 +2,18 @@
<context>
<name>AddressBookPage</name>
<message>
+ <source>&amp;New</source>
+ <translation type="unfinished">&amp;Okusha</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation type="unfinished">&amp;Kopisha</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation type="unfinished">Amakheli ukuthola</translation>
+ </message>
+ <message>
<source>Comma separated file</source>
<extracomment>Expanded name of the CSV file format. See: https://en.wikipedia.org/wiki/Comma-separated_values.</extracomment>
<translation type="unfinished">Ifayela elehlukaniswe ngo khefana.</translation>
@@ -72,6 +84,13 @@
</message>
</context>
<context>
+ <name>bitcoin-core</name>
+ <message>
+ <source>Error: Missing checksum</source>
+ <translation type="unfinished">Iphutha: iChecksum engekho</translation>
+ </message>
+ </context>
+<context>
<name>BitcoinGUI</name>
<message>
<source>&amp;Options…</source>
@@ -133,7 +152,7 @@
<source>Can't list signers</source>
<translation type="unfinished">Akukwazi ukwenza uhlu lwabasayini.</translation>
</message>
-</context>
+ </context>
<context>
<name>CreateWalletDialog</name>
<message>
@@ -143,9 +162,26 @@
</context>
<context>
<name>Intro</name>
- <message>
- <source>(of %1 GB needed)</source>
- <translation type="unfinished">(ku %1 GB odingakalayo)</translation>
+ <message numerus="yes">
+ <source>%n GB of space available</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation type="unfinished">
+ <numerusform />
+ <numerusform />
+ </translation>
</message>
<message numerus="yes">
<source>(sufficient to restore backups %n day(s) old)</source>
@@ -166,6 +202,10 @@
</context>
<context>
<name>SendCoinsDialog</name>
+ <message>
+ <source>Sign failed</source>
+ <translation type="unfinished">Uphawu lwehlulekile</translation>
+ </message>
<message numerus="yes">
<source>Estimated to begin confirmation within %n block(s).</source>
<translation type="unfinished">
diff --git a/src/qt/main.cpp b/src/qt/main.cpp
index 38b0ac71a3..e8f39584ad 100644
--- a/src/qt/main.cpp
+++ b/src/qt/main.cpp
@@ -4,7 +4,7 @@
#include <qt/bitcoin.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <util/translation.h>
#include <util/url.h>
diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp
index 97ee75a31f..dfa33764f6 100644
--- a/src/qt/modaloverlay.cpp
+++ b/src/qt/modaloverlay.cpp
@@ -78,13 +78,16 @@ bool ModalOverlay::event(QEvent* ev) {
return QWidget::event(ev);
}
-void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate)
+void ModalOverlay::setKnownBestHeight(int count, const QDateTime& blockDate, bool presync)
{
- if (count > bestHeaderHeight) {
+ if (!presync && count > bestHeaderHeight) {
bestHeaderHeight = count;
bestHeaderDate = blockDate;
UpdateHeaderSyncLabel();
}
+ if (presync) {
+ UpdateHeaderPresyncLabel(count, blockDate);
+ }
}
void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress)
@@ -158,6 +161,11 @@ void ModalOverlay::UpdateHeaderSyncLabel() {
ui->numberOfBlocksLeft->setText(tr("Unknown. Syncing Headers (%1, %2%)…").arg(bestHeaderHeight).arg(QString::number(100.0 / (bestHeaderHeight + est_headers_left) * bestHeaderHeight, 'f', 1)));
}
+void ModalOverlay::UpdateHeaderPresyncLabel(int height, const QDateTime& blockDate) {
+ int est_headers_left = blockDate.secsTo(QDateTime::currentDateTime()) / Params().GetConsensus().nPowTargetSpacing;
+ ui->numberOfBlocksLeft->setText(tr("Unknown. Pre-syncing Headers (%1, %2%)…").arg(height).arg(QString::number(100.0 / (height + est_headers_left) * height, 'f', 1)));
+}
+
void ModalOverlay::toggleVisibility()
{
showHide(layerIsVisible, true);
diff --git a/src/qt/modaloverlay.h b/src/qt/modaloverlay.h
index 1d8af5cbf6..682c94cd01 100644
--- a/src/qt/modaloverlay.h
+++ b/src/qt/modaloverlay.h
@@ -26,7 +26,7 @@ public:
~ModalOverlay();
void tipUpdate(int count, const QDateTime& blockDate, double nVerificationProgress);
- void setKnownBestHeight(int count, const QDateTime& blockDate);
+ void setKnownBestHeight(int count, const QDateTime& blockDate, bool presync);
// will show or hide the modal layer
void showHide(bool hide = false, bool userRequested = false);
@@ -52,6 +52,7 @@ private:
bool userClosed;
QPropertyAnimation m_animation;
void UpdateHeaderSyncLabel();
+ void UpdateHeaderPresyncLabel(int height, const QDateTime& blockDate);
};
#endif // BITCOIN_QT_MODALOVERLAY_H
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index f3c3af10e0..2b6711ca40 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -10,6 +10,7 @@
#include <qt/forms/ui_optionsdialog.h>
#include <qt/bitcoinunits.h>
+#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/optionsmodel.h>
@@ -18,6 +19,7 @@
#include <validation.h> // for DEFAULT_SCRIPTCHECK_THREADS and MAX_SCRIPTCHECK_THREADS
#include <netbase.h>
#include <txdb.h> // for -dbcache defaults
+#include <util/system.h>
#include <chrono>
@@ -168,6 +170,11 @@ OptionsDialog::~OptionsDialog()
delete ui;
}
+void OptionsDialog::setClientModel(ClientModel* client_model)
+{
+ m_client_model = client_model;
+}
+
void OptionsDialog::setModel(OptionsModel *_model)
{
this->model = _model;
@@ -278,14 +285,23 @@ void OptionsDialog::setOkButtonState(bool fState)
void OptionsDialog::on_resetButton_clicked()
{
- if(model)
- {
+ if (model) {
// confirmation dialog
+ /*: Text explaining that the settings changed will not come into effect
+ until the client is restarted. */
+ QString reset_dialog_text = tr("Client restart required to activate changes.") + "<br><br>";
+ /*: Text explaining to the user that the client's current settings
+ will be backed up at a specific location. %1 is a stand-in
+ argument for the backup location's path. */
+ reset_dialog_text.append(tr("Current settings will be backed up at \"%1\".").arg(m_client_model->dataDir()) + "<br><br>");
+ /*: Text asking the user to confirm if they would like to proceed
+ with a client shutdown. */
+ reset_dialog_text.append(tr("Client will be shut down. Do you want to proceed?"));
+ //: Window title text of pop-up window shown when the user has chosen to reset options.
QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm options reset"),
- tr("Client restart required to activate changes.") + "<br><br>" + tr("Client will be shut down. Do you want to proceed?"),
- QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
+ reset_dialog_text, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
- if(btnRetVal == QMessageBox::Cancel)
+ if (btnRetVal == QMessageBox::Cancel)
return;
/* reset all options and close GUI */
diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h
index 0b7802536c..e5a19d5025 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -8,6 +8,7 @@
#include <QDialog>
#include <QValidator>
+class ClientModel;
class OptionsModel;
class QValidatedLineEdit;
@@ -45,6 +46,7 @@ public:
TAB_NETWORK,
};
+ void setClientModel(ClientModel* client_model);
void setModel(OptionsModel *model);
void setMapper();
void setCurrentTab(OptionsDialog::Tab tab);
@@ -72,6 +74,7 @@ Q_SIGNALS:
private:
Ui::OptionsDialog *ui;
+ ClientModel* m_client_model{nullptr};
OptionsModel *model;
QDataWidgetMapper *mapper;
};
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index a8133f481e..85a3c36f39 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -147,8 +147,6 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent)
{
ui->setupUi(this);
- m_balances.balance = -1;
-
// use a SingleColorIcon for the "out of sync warning" icon
QIcon icon = m_platform_style->SingleColorIcon(QStringLiteral(":/icons/warning"));
ui->labelTransactionsStatus->setIcon(icon);
@@ -177,8 +175,9 @@ void OverviewPage::handleTransactionClicked(const QModelIndex &index)
void OverviewPage::setPrivacy(bool privacy)
{
m_privacy = privacy;
- if (m_balances.balance != -1) {
- setBalance(m_balances);
+ const auto& balances = walletModel->getCachedBalance();
+ if (balances.balance != -1) {
+ setBalance(balances);
}
ui->listTransactions->setVisible(!m_privacy);
@@ -197,7 +196,6 @@ OverviewPage::~OverviewPage()
void OverviewPage::setBalance(const interfaces::WalletBalances& balances)
{
BitcoinUnit unit = walletModel->getOptionsModel()->getDisplayUnit();
- m_balances = balances;
if (walletModel->wallet().isLegacy()) {
if (walletModel->wallet().privateKeysDisabled()) {
ui->labelBalance->setText(BitcoinUnits::formatWithPrivacy(unit, balances.watch_only_balance, BitcoinUnits::SeparatorStyle::ALWAYS, m_privacy));
@@ -276,14 +274,13 @@ void OverviewPage::setWalletModel(WalletModel *model)
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
// Keep up to date with wallet
- interfaces::Wallet& wallet = model->wallet();
- interfaces::WalletBalances balances = wallet.getBalances();
- setBalance(balances);
+ setBalance(model->getCachedBalance());
connect(model, &WalletModel::balanceChanged, this, &OverviewPage::setBalance);
connect(model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &OverviewPage::updateDisplayUnit);
- updateWatchOnlyLabels(wallet.haveWatchOnly() && !model->wallet().privateKeysDisabled());
+ interfaces::Wallet& wallet = model->wallet();
+ updateWatchOnlyLabels(wallet.haveWatchOnly() && !wallet.privateKeysDisabled());
connect(model, &WalletModel::notifyWatchonlyChanged, [this](bool showWatchOnly) {
updateWatchOnlyLabels(showWatchOnly && !walletModel->wallet().privateKeysDisabled());
});
@@ -306,10 +303,10 @@ void OverviewPage::changeEvent(QEvent* e)
void OverviewPage::updateDisplayUnit()
{
- if(walletModel && walletModel->getOptionsModel())
- {
- if (m_balances.balance != -1) {
- setBalance(m_balances);
+ if (walletModel && walletModel->getOptionsModel()) {
+ const auto& balances = walletModel->getCachedBalance();
+ if (balances.balance != -1) {
+ setBalance(balances);
}
// Update txdelegate->unit with the current unit
diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h
index 058df1a8c5..56f45907db 100644
--- a/src/qt/overviewpage.h
+++ b/src/qt/overviewpage.h
@@ -52,7 +52,6 @@ private:
Ui::OverviewPage *ui;
ClientModel *clientModel;
WalletModel *walletModel;
- interfaces::WalletBalances m_balances;
bool m_privacy{false};
const PlatformStyle* m_platform_style;
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index b791fd30c4..295450d6b7 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -661,7 +661,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_
setNumConnections(model->getNumConnections());
connect(model, &ClientModel::numConnectionsChanged, this, &RPCConsole::setNumConnections);
- setNumBlocks(bestblock_height, QDateTime::fromSecsSinceEpoch(bestblock_date), verification_progress, false);
+ setNumBlocks(bestblock_height, QDateTime::fromSecsSinceEpoch(bestblock_date), verification_progress, SyncType::BLOCK_SYNC);
connect(model, &ClientModel::numBlocksChanged, this, &RPCConsole::setNumBlocks);
updateNetworkState();
@@ -973,9 +973,9 @@ void RPCConsole::setNetworkActive(bool networkActive)
updateNetworkState();
}
-void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers)
+void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype)
{
- if (!headers) {
+ if (synctype == SyncType::BLOCK_SYNC) {
ui->numberOfBlocks->setText(QString::number(count));
ui->lastBlockTime->setText(blockDate.toString());
}
@@ -1162,7 +1162,6 @@ void RPCConsole::updateDetailWidget()
if (!stats->nodeStats.addrLocal.empty())
peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
ui->peerHeading->setText(peerAddrDetails);
- ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStats.nServices));
QString bip152_hb_settings;
if (stats->nodeStats.m_bip152_highbandwidth_to) bip152_hb_settings = ts.to;
if (stats->nodeStats.m_bip152_highbandwidth_from) bip152_hb_settings += (bip152_hb_settings.isEmpty() ? ts.from : QLatin1Char('/') + ts.from);
@@ -1183,11 +1182,11 @@ void RPCConsole::updateDetailWidget()
ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
ui->peerConnectionType->setText(GUIUtil::ConnectionTypeToQString(stats->nodeStats.m_conn_type, /*prepend_direction=*/true));
ui->peerNetwork->setText(GUIUtil::NetworkToQString(stats->nodeStats.m_network));
- if (stats->nodeStats.m_permissionFlags == NetPermissionFlags::None) {
+ if (stats->nodeStats.m_permission_flags == NetPermissionFlags::None) {
ui->peerPermissions->setText(ts.na);
} else {
QStringList permissions;
- for (const auto& permission : NetPermissions::ToStrings(stats->nodeStats.m_permissionFlags)) {
+ for (const auto& permission : NetPermissions::ToStrings(stats->nodeStats.m_permission_flags)) {
permissions.append(QString::fromStdString(permission));
}
ui->peerPermissions->setText(permissions.join(" & "));
@@ -1197,6 +1196,7 @@ void RPCConsole::updateDetailWidget()
// This check fails for example if the lock was busy and
// nodeStateStats couldn't be fetched.
if (stats->fNodeStateStatsAvailable) {
+ ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStateStats.their_services));
// Sync height is init to -1
if (stats->nodeStateStats.nSyncHeight > -1) {
ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 1a54fe0cad..a3c713e966 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -9,6 +9,7 @@
#include <config/bitcoin-config.h>
#endif
+#include <qt/clientmodel.h>
#include <qt/guiutil.h>
#include <qt/peertablemodel.h>
@@ -19,7 +20,6 @@
#include <QThread>
#include <QWidget>
-class ClientModel;
class PlatformStyle;
class RPCExecutor;
class RPCTimerInterface;
@@ -121,7 +121,7 @@ public Q_SLOTS:
/** Set network state shown in the UI */
void setNetworkActive(bool networkActive);
/** Set number of blocks and last block date shown in the UI */
- void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers);
+ void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype);
/** Set size (number of transactions and memory usage) of the mempool in the UI */
void setMempoolSize(long numberOfTxs, size_t dynUsage);
/** Go forward or back in history */
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index bd44d12781..53c352b393 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -164,11 +164,9 @@ void SendCoinsDialog::setModel(WalletModel *_model)
}
}
- interfaces::WalletBalances balances = _model->wallet().getBalances();
- setBalance(balances);
connect(_model, &WalletModel::balanceChanged, this, &SendCoinsDialog::setBalance);
- connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::updateDisplayUnit);
- updateDisplayUnit();
+ connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::refreshBalance);
+ refreshBalance();
// Coin Control
connect(_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
@@ -711,9 +709,9 @@ void SendCoinsDialog::setBalance(const interfaces::WalletBalances& balances)
}
}
-void SendCoinsDialog::updateDisplayUnit()
+void SendCoinsDialog::refreshBalance()
{
- setBalance(model->wallet().getBalances());
+ setBalance(model->getCachedBalance());
ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
updateSmartFeeLabel();
}
@@ -786,7 +784,7 @@ void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry)
m_coin_control->fAllowWatchOnly = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner();
// Calculate available amount to send.
- CAmount amount = model->wallet().getAvailableBalance(*m_coin_control);
+ CAmount amount = model->getAvailableBalance(m_coin_control.get());
for (int i = 0; i < ui->entries->count(); ++i) {
SendCoinsEntry* e = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
if (e && !e->isHidden() && e != entry) {
@@ -841,7 +839,7 @@ void SendCoinsDialog::updateCoinControlState()
m_coin_control->fAllowWatchOnly = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner();
}
-void SendCoinsDialog::updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state) {
+void SendCoinsDialog::updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state) {
if (sync_state == SynchronizationState::POST_INIT) {
updateSmartFeeLabel();
}
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index 400503d0c0..dcdf189532 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_QT_SENDCOINSDIALOG_H
#define BITCOIN_QT_SENDCOINSDIALOG_H
+#include <qt/clientmodel.h>
#include <qt/walletmodel.h>
#include <QDialog>
@@ -12,7 +13,6 @@
#include <QString>
#include <QTimer>
-class ClientModel;
class PlatformStyle;
class SendCoinsEntry;
class SendCoinsRecipient;
@@ -97,7 +97,7 @@ private Q_SLOTS:
void on_buttonMinimizeFee_clicked();
void removeEntry(SendCoinsEntry* entry);
void useAvailableBalance(SendCoinsEntry* entry);
- void updateDisplayUnit();
+ void refreshBalance();
void coinControlFeatureChanged(bool);
void coinControlButtonClicked();
void coinControlChangeChecked(int);
@@ -111,7 +111,7 @@ private Q_SLOTS:
void coinControlClipboardLowOutput();
void coinControlClipboardChange();
void updateFeeSectionControls();
- void updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state);
+ void updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, SyncType synctype, SynchronizationState sync_state);
void updateSmartFeeLabel();
Q_SIGNALS:
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index a4dfffa387..bf04a6dd5f 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -44,7 +44,7 @@ SplashScreen::SplashScreen(const NetworkStyle* networkStyle)
QString titleText = PACKAGE_NAME;
QString versionText = QString("Version %1").arg(QString::fromStdString(FormatFullVersion()));
QString copyrightText = QString::fromUtf8(CopyrightHolders(strprintf("\xc2\xA9 %u-%u ", 2009, COPYRIGHT_YEAR)).c_str());
- QString titleAddText = networkStyle->getTitleAddText();
+ const QString& titleAddText = networkStyle->getTitleAddText();
QString font = QApplication::font().toString();
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index de23f51c92..846fa519ee 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -43,8 +43,6 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
#endif
#endif
-using node::NodeContext;
-
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
const std::function<std::vector<const char*>()> G_TEST_COMMAND_LINE_ARGUMENTS{};
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index 7671bfc739..b71dfb0e9f 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -129,6 +129,13 @@ void BumpFee(TransactionView& view, const uint256& txid, bool expectDisabled, st
QVERIFY(text.indexOf(QString::fromStdString(expectError)) != -1);
}
+void CompareBalance(WalletModel& walletModel, CAmount expected_balance, QLabel* balance_label_to_check)
+{
+ BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit();
+ QString balanceComparison = BitcoinUnits::formatWithUnit(unit, expected_balance, false, BitcoinUnits::SeparatorStyle::ALWAYS);
+ QCOMPARE(balance_label_to_check->text().trimmed(), balanceComparison);
+}
+
//! Simple qt wallet tests.
//
// Test widgets can be debugged interactively calling show() on them and
@@ -168,14 +175,14 @@ void TestGUI(interfaces::Node& node)
if (!wallet->AddWalletDescriptor(w_desc, provider, "", false)) assert(false);
CTxDestination dest = GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type);
wallet->SetAddressBook(dest, "", "receive");
- wallet->SetLastBlockProcessed(105, node.context()->chainman->ActiveChain().Tip()->GetBlockHash());
+ wallet->SetLastBlockProcessed(105, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash()));
}
{
WalletRescanReserver reserver(*wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet->ScanForWalletTransactions(Params().GetConsensus().hashGenesisBlock, 0 /* block height */, {} /* max height */, reserver, true /* fUpdate */);
+ CWallet::ScanResult result = wallet->ScanForWalletTransactions(Params().GetConsensus().hashGenesisBlock, /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/false);
QCOMPARE(result.status, CWallet::ScanResult::SUCCESS);
- QCOMPARE(result.last_scanned_block, node.context()->chainman->ActiveChain().Tip()->GetBlockHash());
+ QCOMPARE(result.last_scanned_block, WITH_LOCK(node.context()->chainman->GetMutex(), return node.context()->chainman->ActiveChain().Tip()->GetBlockHash()));
QVERIFY(result.last_failed_block.IsNull());
}
wallet->SetBroadcastTransactions(true);
@@ -195,15 +202,10 @@ void TestGUI(interfaces::Node& node)
sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel);
- {
- // Check balance in send dialog
- QLabel* balanceLabel = sendCoinsDialog.findChild<QLabel*>("labelBalance");
- QString balanceText = balanceLabel->text();
- BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit();
- CAmount balance = walletModel.wallet().getBalance();
- QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::SeparatorStyle::ALWAYS);
- QCOMPARE(balanceText, balanceComparison);
- }
+ // Update walletModel cached balance which will trigger an update for the 'labelBalance' QLabel.
+ walletModel.pollBalanceChanged();
+ // Check balance in send dialog
+ CompareBalance(walletModel, walletModel.wallet().getBalance(), sendCoinsDialog.findChild<QLabel*>("labelBalance"));
// Send two transactions, and verify they are added to transaction list.
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
@@ -223,12 +225,8 @@ void TestGUI(interfaces::Node& node)
// Check current balance on OverviewPage
OverviewPage overviewPage(platformStyle.get());
overviewPage.setWalletModel(&walletModel);
- QLabel* balanceLabel = overviewPage.findChild<QLabel*>("labelBalance");
- QString balanceText = balanceLabel->text().trimmed();
- BitcoinUnit unit = walletModel.getOptionsModel()->getDisplayUnit();
- CAmount balance = walletModel.wallet().getBalance();
- QString balanceComparison = BitcoinUnits::formatWithUnit(unit, balance, false, BitcoinUnits::SeparatorStyle::ALWAYS);
- QCOMPARE(balanceText, balanceComparison);
+ walletModel.pollBalanceChanged(); // Manual balance polling update
+ CompareBalance(walletModel, walletModel.wallet().getBalance(), overviewPage.findChild<QLabel*>("labelBalance"));
// Check Request Payment button
ReceiveCoinsDialog receiveCoinsDialog(platformStyle.get());
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index d27ddf1aba..8762ba9ab3 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -262,9 +262,13 @@ void CreateWalletActivity::createWallet()
}
QTimer::singleShot(500ms, worker(), [this, name, flags] {
- std::unique_ptr<interfaces::Wallet> wallet = node().walletLoader().createWallet(name, m_passphrase, flags, m_error_message, m_warning_message);
+ auto wallet{node().walletLoader().createWallet(name, m_passphrase, flags, m_warning_message)};
- if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
+ if (wallet) {
+ m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(*wallet));
+ } else {
+ m_error_message = util::ErrorString(wallet);
+ }
QTimer::singleShot(500ms, this, &CreateWalletActivity::finish);
});
@@ -293,6 +297,10 @@ void CreateWalletActivity::create()
} catch (const std::runtime_error& e) {
QMessageBox::critical(nullptr, tr("Can't list signers"), e.what());
}
+ if (signers.size() > 1) {
+ QMessageBox::critical(nullptr, tr("Too many external signers found"), QString::fromStdString("More than one external signer found. Please connect only one at a time."));
+ signers.clear();
+ }
m_create_wallet_dialog->setSigners(signers);
m_create_wallet_dialog->setWindowModality(Qt::ApplicationModal);
@@ -343,9 +351,13 @@ void OpenWalletActivity::open(const std::string& path)
tr("Opening Wallet <b>%1</b>…").arg(name.toHtmlEscaped()));
QTimer::singleShot(0, worker(), [this, path] {
- std::unique_ptr<interfaces::Wallet> wallet = node().walletLoader().loadWallet(path, m_error_message, m_warning_message);
+ auto wallet{node().walletLoader().loadWallet(path, m_warning_message)};
- if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
+ if (wallet) {
+ m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(*wallet));
+ } else {
+ m_error_message = util::ErrorString(wallet);
+ }
QTimer::singleShot(0, this, &OpenWalletActivity::finish);
});
@@ -373,3 +385,50 @@ void LoadWalletsActivity::load()
QTimer::singleShot(0, this, [this] { Q_EMIT finished(); });
});
}
+
+RestoreWalletActivity::RestoreWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
+ : WalletControllerActivity(wallet_controller, parent_widget)
+{
+}
+
+void RestoreWalletActivity::restore(const fs::path& backup_file, const std::string& wallet_name)
+{
+ QString name = QString::fromStdString(wallet_name);
+
+ showProgressDialog(
+ //: Title of progress window which is displayed when wallets are being restored.
+ tr("Restore Wallet"),
+ /*: Descriptive text of the restore wallets progress window which indicates to
+ the user that wallets are currently being restored.*/
+ tr("Restoring Wallet <b>%1</b>…").arg(name.toHtmlEscaped()));
+
+ QTimer::singleShot(0, worker(), [this, backup_file, wallet_name] {
+ auto wallet{node().walletLoader().restoreWallet(backup_file, wallet_name, m_warning_message)};
+
+ if (wallet) {
+ m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(*wallet));
+ } else {
+ m_error_message = util::ErrorString(wallet);
+ }
+
+ QTimer::singleShot(0, this, &RestoreWalletActivity::finish);
+ });
+}
+
+void RestoreWalletActivity::finish()
+{
+ if (!m_error_message.empty()) {
+ //: Title of message box which is displayed when the wallet could not be restored.
+ QMessageBox::critical(m_parent_widget, tr("Restore wallet failed"), QString::fromStdString(m_error_message.translated));
+ } else if (!m_warning_message.empty()) {
+ //: Title of message box which is displayed when the wallet is restored with some warning.
+ QMessageBox::warning(m_parent_widget, tr("Restore wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated));
+ } else {
+ //: Title of message box which is displayed when the wallet is successfully restored.
+ QMessageBox::information(m_parent_widget, tr("Restore wallet message"), QString::fromStdString(Untranslated("Wallet restored successfully \n").translated));
+ }
+
+ if (m_wallet_model) Q_EMIT restored(m_wallet_model);
+
+ Q_EMIT finished();
+}
diff --git a/src/qt/walletcontroller.h b/src/qt/walletcontroller.h
index 24f85c258c..fcd65756c6 100644
--- a/src/qt/walletcontroller.h
+++ b/src/qt/walletcontroller.h
@@ -33,6 +33,10 @@ class Node;
class Wallet;
} // namespace interfaces
+namespace fs {
+class path;
+}
+
class AskPassphraseDialog;
class CreateWalletActivity;
class CreateWalletDialog;
@@ -155,4 +159,20 @@ public:
void load();
};
+class RestoreWalletActivity : public WalletControllerActivity
+{
+ Q_OBJECT
+
+public:
+ RestoreWalletActivity(WalletController* wallet_controller, QWidget* parent_widget);
+
+ void restore(const fs::path& backup_file, const std::string& wallet_name);
+
+Q_SIGNALS:
+ void restored(WalletModel* wallet_model);
+
+private:
+ void finish();
+};
+
#endif // BITCOIN_QT_WALLETCONTROLLER_H
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 6b38e207d3..adc7793916 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -212,7 +212,15 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard)
return;
}
std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
- data.assign(std::istream_iterator<unsigned char>{in}, {});
+ data.assign(std::istreambuf_iterator<char>{in}, {});
+
+ // Some psbt files may be base64 strings in the file rather than binary data
+ std::string b64_str{data.begin(), data.end()};
+ b64_str.erase(b64_str.find_last_not_of(" \t\n\r\f\v") + 1); // Trim trailing whitespace
+ auto b64_dec = DecodeBase64(b64_str);
+ if (b64_dec.has_value()) {
+ data = b64_dec.value();
+ }
}
std::string error;
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index ab4d1cae3f..c6f3f5b00c 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -67,6 +67,10 @@ WalletModel::~WalletModel()
void WalletModel::startPollBalance()
{
+ // Update the cached balance right away, so every view can make use of it,
+ // so them don't need to waste resources recalculating it.
+ pollBalanceChanged();
+
// This timer will be fired repeatedly to update the balance
// Since the QTimer::timeout is a private signal, it cannot be used
// in the GUIUtil::ExceptionSafeConnect directly.
@@ -120,12 +124,17 @@ void WalletModel::pollBalanceChanged()
void WalletModel::checkBalanceChanged(const interfaces::WalletBalances& new_balances)
{
- if(new_balances.balanceChanged(m_cached_balances)) {
+ if (new_balances.balanceChanged(m_cached_balances)) {
m_cached_balances = new_balances;
Q_EMIT balanceChanged(new_balances);
}
}
+interfaces::WalletBalances WalletModel::getCachedBalance() const
+{
+ return m_cached_balances;
+}
+
void WalletModel::updateTransaction()
{
// Balance and number of transactions might have changed
@@ -194,7 +203,9 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
return DuplicateAddress;
}
- CAmount nBalance = m_wallet->getAvailableBalance(coinControl);
+ // If no coin was manually selected, use the cached balance
+ // Future: can merge this call with 'createTransaction'.
+ CAmount nBalance = getAvailableBalance(&coinControl);
if(total > nBalance)
{
@@ -204,10 +215,10 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
{
CAmount nFeeRequired = 0;
int nChangePosRet = -1;
- bilingual_str error;
auto& newTx = transaction.getWtx();
- newTx = m_wallet->createTransaction(vecSend, coinControl, !wallet().privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired, error);
+ const auto& res = m_wallet->createTransaction(vecSend, coinControl, !wallet().privateKeysDisabled() /* sign */, nChangePosRet, nFeeRequired);
+ newTx = res ? *res : nullptr;
transaction.setTransactionFee(nFeeRequired);
if (fSubtractFeeFromAmount && newTx)
transaction.reassignAmounts(nChangePosRet);
@@ -218,7 +229,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
{
return SendCoinsReturn(AmountWithFeeExceedsBalance);
}
- Q_EMIT message(tr("Send Coins"), QString::fromStdString(error.translated),
+ Q_EMIT message(tr("Send Coins"), QString::fromStdString(util::ErrorString(res).translated),
CClientUIInterface::MSG_ERROR);
return TransactionCreationFailed;
}
@@ -306,6 +317,11 @@ WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
{
if(!m_wallet->isCrypted())
{
+ // A previous bug allowed for watchonly wallets to be encrypted (encryption keys set, but nothing is actually encrypted).
+ // To avoid misrepresenting the encryption status of such wallets, we only return NoKeys for watchonly wallets that are unencrypted.
+ if (m_wallet->privateKeysDisabled()) {
+ return NoKeys;
+ }
return Unencrypted;
}
else if(m_wallet->isLocked())
@@ -597,3 +613,8 @@ uint256 WalletModel::getLastBlockProcessed() const
{
return m_client_model ? m_client_model->getBestBlockHash() : uint256{};
}
+
+CAmount WalletModel::getAvailableBalance(const CCoinControl* control)
+{
+ return control && control->HasSelected() ? wallet().getAvailableBalance(*control) : getCachedBalance().balance;
+}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index a52290dee8..73dfe0386a 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -71,6 +71,7 @@ public:
enum EncryptionStatus
{
+ NoKeys, // wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)
Unencrypted, // !wallet->IsCrypted()
Locked, // wallet->IsCrypted() && wallet->IsLocked()
Unlocked // wallet->IsCrypted() && !wallet->IsLocked()
@@ -154,6 +155,13 @@ public:
uint256 getLastBlockProcessed() const;
+ // Retrieve the cached wallet balance
+ interfaces::WalletBalances getCachedBalance() const;
+
+ // If coin control has selected outputs, searches the total amount inside the wallet.
+ // Otherwise, uses the wallet's cached available balance.
+ CAmount getAvailableBalance(const wallet::CCoinControl* control);
+
private:
std::unique_ptr<interfaces::Wallet> m_wallet;
std::unique_ptr<interfaces::Handler> m_handler_unload;
diff --git a/src/random.cpp b/src/random.cpp
index fca4b5041a..f92e679a00 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -10,7 +10,7 @@
#include <crypto/sha512.h>
#include <support/cleanse.h>
#ifdef WIN32
-#include <compat.h> // for Windows API
+#include <compat/compat.h>
#include <wincrypt.h>
#endif
#include <logging.h>
diff --git a/src/random.h b/src/random.h
index b92c29f0be..5fe20c5f76 100644
--- a/src/random.h
+++ b/src/random.h
@@ -11,6 +11,7 @@
#include <span.h>
#include <uint256.h>
+#include <cassert>
#include <chrono>
#include <cstdint>
#include <limits>
@@ -236,13 +237,19 @@ public:
template <typename Tp>
Tp rand_uniform_delay(const Tp& time, typename Tp::duration range)
{
- using Dur = typename Tp::duration;
- Dur dur{range.count() > 0 ? /* interval [0..range) */ Dur{randrange(range.count())} :
- range.count() < 0 ? /* interval (range..0] */ -Dur{randrange(-range.count())} :
- /* interval [0..0] */ Dur{0}};
- return time + dur;
+ return time + rand_uniform_duration<Tp>(range);
}
+ /** Generate a uniform random duration in the range from 0 (inclusive) to range (exclusive). */
+ template <typename Chrono>
+ typename Chrono::duration rand_uniform_duration(typename Chrono::duration range) noexcept
+ {
+ using Dur = typename Chrono::duration;
+ return range.count() > 0 ? /* interval [0..range) */ Dur{randrange(range.count())} :
+ range.count() < 0 ? /* interval (range..0] */ -Dur{randrange(-range.count())} :
+ /* interval [0..0] */ Dur{0};
+ };
+
// Compatibility with the C++11 UniformRandomBitGenerator concept
typedef uint64_t result_type;
static constexpr uint64_t min() { return 0; }
diff --git a/src/randomenv.cpp b/src/randomenv.cpp
index c5dca346d6..9e58180b7a 100644
--- a/src/randomenv.cpp
+++ b/src/randomenv.cpp
@@ -15,7 +15,7 @@
#include <support/cleanse.h>
#include <util/time.h> // for GetTime()
#ifdef WIN32
-#include <compat.h> // for Windows API
+#include <compat/compat.h>
#endif
#include <algorithm>
diff --git a/src/rest.cpp b/src/rest.cpp
index 43c248b03b..7f00db2222 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -590,45 +590,31 @@ static bool rest_chaininfo(const std::any& context, HTTPRequest* req, const std:
}
}
-static bool rest_mempool_info(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
+static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::string& str_uri_part)
{
if (!CheckWarmup(req))
return false;
- const CTxMemPool* mempool = GetMemPool(context, req);
- if (!mempool) return false;
- std::string param;
- const RESTResponseFormat rf = ParseDataFormat(param, strURIPart);
-
- switch (rf) {
- case RESTResponseFormat::JSON: {
- UniValue mempoolInfoObject = MempoolInfoToJSON(*mempool);
- std::string strJSON = mempoolInfoObject.write() + "\n";
- req->WriteHeader("Content-Type", "application/json");
- req->WriteReply(HTTP_OK, strJSON);
- return true;
- }
- default: {
- return RESTERR(req, HTTP_NOT_FOUND, "output format not found (available: json)");
- }
+ std::string param;
+ const RESTResponseFormat rf = ParseDataFormat(param, str_uri_part);
+ if (param != "contents" && param != "info") {
+ return RESTERR(req, HTTP_BAD_REQUEST, "Invalid URI format. Expected /rest/mempool/<info|contents>.json");
}
-}
-static bool rest_mempool_contents(const std::any& context, HTTPRequest* req, const std::string& strURIPart)
-{
- if (!CheckWarmup(req)) return false;
const CTxMemPool* mempool = GetMemPool(context, req);
if (!mempool) return false;
- std::string param;
- const RESTResponseFormat rf = ParseDataFormat(param, strURIPart);
switch (rf) {
case RESTResponseFormat::JSON: {
- UniValue mempoolObject = MempoolToJSON(*mempool, true);
+ std::string str_json;
+ if (param == "contents") {
+ str_json = MempoolToJSON(*mempool, true).write() + "\n";
+ } else {
+ str_json = MempoolInfoToJSON(*mempool).write() + "\n";
+ }
- std::string strJSON = mempoolObject.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
- req->WriteReply(HTTP_OK, strJSON);
+ req->WriteReply(HTTP_OK, str_json);
return true;
}
default: {
@@ -798,14 +784,18 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
ChainstateManager* maybe_chainman = GetChainman(context, req);
if (!maybe_chainman) return false;
ChainstateManager& chainman = *maybe_chainman;
+ decltype(chainman.ActiveHeight()) active_height;
+ uint256 active_hash;
{
- auto process_utxos = [&vOutPoints, &outs, &hits](const CCoinsView& view, const CTxMemPool* mempool) {
+ auto process_utxos = [&vOutPoints, &outs, &hits, &active_height, &active_hash, &chainman](const CCoinsView& view, const CTxMemPool* mempool) EXCLUSIVE_LOCKS_REQUIRED(chainman.GetMutex()) {
for (const COutPoint& vOutPoint : vOutPoints) {
Coin coin;
bool hit = (!mempool || !mempool->isSpent(vOutPoint)) && view.GetCoin(vOutPoint, coin);
hits.push_back(hit);
if (hit) outs.emplace_back(std::move(coin));
}
+ active_height = chainman.ActiveHeight();
+ active_hash = chainman.ActiveTip()->GetBlockHash();
};
if (fCheckMemPool) {
@@ -833,7 +823,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
// serialize data
// use exact same output as mentioned in Bip64
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
- ssGetUTXOResponse << chainman.ActiveChain().Height() << chainman.ActiveChain().Tip()->GetBlockHash() << bitmap << outs;
+ ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
std::string ssGetUTXOResponseString = ssGetUTXOResponse.str();
req->WriteHeader("Content-Type", "application/octet-stream");
@@ -843,7 +833,7 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
case RESTResponseFormat::HEX: {
CDataStream ssGetUTXOResponse(SER_NETWORK, PROTOCOL_VERSION);
- ssGetUTXOResponse << chainman.ActiveChain().Height() << chainman.ActiveChain().Tip()->GetBlockHash() << bitmap << outs;
+ ssGetUTXOResponse << active_height << active_hash << bitmap << outs;
std::string strHex = HexStr(ssGetUTXOResponse) + "\n";
req->WriteHeader("Content-Type", "text/plain");
@@ -856,8 +846,8 @@ static bool rest_getutxos(const std::any& context, HTTPRequest* req, const std::
// pack in some essentials
// use more or less the same output as mentioned in Bip64
- objGetUTXOResponse.pushKV("chainHeight", chainman.ActiveChain().Height());
- objGetUTXOResponse.pushKV("chaintipHash", chainman.ActiveChain().Tip()->GetBlockHash().GetHex());
+ objGetUTXOResponse.pushKV("chainHeight", active_height);
+ objGetUTXOResponse.pushKV("chaintipHash", active_hash.GetHex());
objGetUTXOResponse.pushKV("bitmap", bitmapStringRepresentation);
UniValue utxos(UniValue::VARR);
@@ -946,8 +936,7 @@ static const struct {
{"/rest/blockfilter/", rest_block_filter},
{"/rest/blockfilterheaders/", rest_filter_header},
{"/rest/chaininfo", rest_chaininfo},
- {"/rest/mempool/info", rest_mempool_info},
- {"/rest/mempool/contents", rest_mempool_contents},
+ {"/rest/mempool/", rest_mempool},
{"/rest/headers/", rest_headers},
{"/rest/getutxos", rest_getutxos},
{"/rest/blockhashbyheight/", rest_blockhash_by_height},
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 9766a237c7..d1daf06732 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -39,6 +39,7 @@
#include <univalue.h>
#include <util/check.h>
#include <util/strencodings.h>
+#include <util/system.h>
#include <util/translation.h>
#include <validation.h>
#include <validationinterface.h>
@@ -396,7 +397,7 @@ static RPCHelpMan syncwithvalidationinterfacequeue()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
SyncWithValidationInterfaceQueue();
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -440,6 +441,11 @@ static RPCHelpMan getblockfrompeer()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
+ RPCTypeCheck(request.params, {
+ UniValue::VSTR, // blockhash
+ UniValue::VNUM, // peer_id
+ });
+
const NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node);
PeerManager& peerman = EnsurePeerman(node);
@@ -598,6 +604,30 @@ static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex* pblo
return blockUndo;
}
+const RPCResult getblock_vin{
+ RPCResult::Type::ARR, "vin", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::ELISION, "", "The same output as verbosity = 2"},
+ {RPCResult::Type::OBJ, "prevout", "(Only if undo information is available)",
+ {
+ {RPCResult::Type::BOOL, "generated", "Coinbase or not"},
+ {RPCResult::Type::NUM, "height", "The height of the prevout"},
+ {RPCResult::Type::STR_AMOUNT, "value", "The value in " + CURRENCY_UNIT},
+ {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the public key script"},
+ {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw public key script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
+ {RPCResult::Type::STR, "type", "The type (one of: " + GetAllOutputTypes() + ")"},
+ }},
+ }},
+ }},
+ }
+};
+
static RPCHelpMan getblock()
{
return RPCHelpMan{"getblock",
@@ -657,26 +687,7 @@ static RPCHelpMan getblock()
{
{RPCResult::Type::OBJ, "", "",
{
- {RPCResult::Type::ARR, "vin", "",
- {
- {RPCResult::Type::OBJ, "", "",
- {
- {RPCResult::Type::ELISION, "", "The same output as verbosity = 2"},
- {RPCResult::Type::OBJ, "prevout", "(Only if undo information is available)",
- {
- {RPCResult::Type::BOOL, "generated", "Coinbase or not"},
- {RPCResult::Type::NUM, "height", "The height of the prevout"},
- {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT},
- {RPCResult::Type::OBJ, "scriptPubKey", "",
- {
- {RPCResult::Type::STR, "asm", "The asm"},
- {RPCResult::Type::STR, "hex", "The hex"},
- {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
- {RPCResult::Type::STR, "type", "The type (one of: " + GetAllOutputTypes() + ")"},
- }},
- }},
- }},
- }},
+ getblock_vin,
}},
}},
}},
@@ -756,7 +767,7 @@ static RPCHelpMan pruneblockchain()
ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ Chainstate& active_chainstate = chainman.ActiveChainstate();
CChain& active_chain = active_chainstate.m_chain;
int heightParam = request.params[0].getInt<int>();
@@ -822,9 +833,9 @@ static std::optional<kernel::CCoinsStats> GetUTXOStats(CCoinsView* view, node::B
// Use CoinStatsIndex if it is requested and available and a hash_type of Muhash or None was requested
if ((hash_type == kernel::CoinStatsHashType::MUHASH || hash_type == kernel::CoinStatsHashType::NONE) && g_coin_stats_index && index_requested) {
if (pindex) {
- return g_coin_stats_index->LookUpStats(pindex);
+ return g_coin_stats_index->LookUpStats(*pindex);
} else {
- CBlockIndex* block_index = WITH_LOCK(::cs_main, return blockman.LookupBlockIndex(view->GetBestBlock()));
+ CBlockIndex& block_index = *CHECK_NONFATAL(WITH_LOCK(::cs_main, return blockman.LookupBlockIndex(view->GetBestBlock())));
return g_coin_stats_index->LookUpStats(block_index);
}
}
@@ -845,7 +856,7 @@ static RPCHelpMan gettxoutsetinfo()
"Note this call may take some time if you are not using coinstatsindex.\n",
{
{"hash_type", RPCArg::Type::STR, RPCArg::Default{"hash_serialized_2"}, "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."},
- {"hash_or_height", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "The block hash or height of the target height (only available with coinstatsindex).", "", {"", "string or numeric"}},
+ {"hash_or_height", RPCArg::Type::NUM, RPCArg::DefaultHint{"the current best block"}, "The block hash or height of the target height (only available with coinstatsindex).", "", {"", "string or numeric"}},
{"use_index", RPCArg::Type::BOOL, RPCArg::Default{true}, "Use coinstatsindex, if available."},
},
RPCResult{
@@ -881,6 +892,7 @@ static RPCHelpMan gettxoutsetinfo()
HelpExampleCli("gettxoutsetinfo", R"("none")") +
HelpExampleCli("gettxoutsetinfo", R"("none" 1000)") +
HelpExampleCli("gettxoutsetinfo", R"("none" '"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"')") +
+ HelpExampleCli("-named gettxoutsetinfo", R"(hash_type='muhash' use_index='false')") +
HelpExampleRpc("gettxoutsetinfo", "") +
HelpExampleRpc("gettxoutsetinfo", R"("none")") +
HelpExampleRpc("gettxoutsetinfo", R"("none", 1000)") +
@@ -896,7 +908,7 @@ static RPCHelpMan gettxoutsetinfo()
NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node);
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ Chainstate& active_chainstate = chainman.ActiveChainstate();
active_chainstate.ForceFlushStateToDisk();
CCoinsView* coins_view;
@@ -917,6 +929,9 @@ static RPCHelpMan gettxoutsetinfo()
throw JSONRPCError(RPC_INVALID_PARAMETER, "hash_serialized_2 hash type cannot be queried for a specific block");
}
+ if (!index_requested) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot set use_index to false when querying for a specific block");
+ }
pindex = ParseHashOrHeight(request.params[1], chainman);
}
@@ -1001,9 +1016,9 @@ static RPCHelpMan gettxout()
{RPCResult::Type::NUM, "confirmations", "The number of confirmations"},
{RPCResult::Type::STR_AMOUNT, "value", "The transaction value in " + CURRENCY_UNIT},
{RPCResult::Type::OBJ, "scriptPubKey", "", {
- {RPCResult::Type::STR, "asm", ""},
+ {RPCResult::Type::STR, "asm", "Disassembly of the public key script"},
{RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
- {RPCResult::Type::STR_HEX, "hex", ""},
+ {RPCResult::Type::STR_HEX, "hex", "The raw public key script bytes, hex-encoded"},
{RPCResult::Type::STR, "type", "The type, eg pubkeyhash"},
{RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
}},
@@ -1033,7 +1048,7 @@ static RPCHelpMan gettxout()
fMempool = request.params[2].get_bool();
Coin coin;
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ Chainstate& active_chainstate = chainman.ActiveChainstate();
CCoinsViewCache* coins_view = &active_chainstate.CoinsTip();
if (fMempool) {
@@ -1041,11 +1056,11 @@ static RPCHelpMan gettxout()
LOCK(mempool.cs);
CCoinsViewMemPool view(coins_view, mempool);
if (!view.GetCoin(out, coin) || mempool.isSpent(out)) {
- return NullUniValue;
+ return UniValue::VNULL;
}
} else {
if (!coins_view->GetCoin(out, coin)) {
- return NullUniValue;
+ return UniValue::VNULL;
}
}
@@ -1090,7 +1105,7 @@ static RPCHelpMan verifychain()
ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ Chainstate& active_chainstate = chainman.ActiveChainstate();
return CVerifyDB().VerifyDB(
active_chainstate, chainman.GetParams().GetConsensus(), active_chainstate.CoinsTip(), check_level, check_depth);
},
@@ -1218,7 +1233,7 @@ RPCHelpMan getblockchaininfo()
const ArgsManager& args{EnsureAnyArgsman(request.context)};
ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ Chainstate& active_chainstate = chainman.ActiveChainstate();
const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())};
const int height{tip.nHeight};
@@ -1313,7 +1328,7 @@ static RPCHelpMan getdeploymentinfo()
{
const ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
- const CChainState& active_chainstate = chainman.ActiveChainstate();
+ const Chainstate& active_chainstate = chainman.ActiveChainstate();
const CBlockIndex* blockindex;
if (request.params[0].isNull()) {
@@ -1483,7 +1498,7 @@ static RPCHelpMan preciousblock()
throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -1524,7 +1539,7 @@ static RPCHelpMan invalidateblock()
throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -1564,7 +1579,7 @@ static RPCHelpMan reconsiderblock()
throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString());
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -2083,7 +2098,7 @@ static RPCHelpMan scantxoutset()
CoinsViewScanReserver reserver;
if (reserver.reserve()) {
// no scan in progress
- return NullUniValue;
+ return UniValue::VNULL;
}
result.pushKV("progress", g_scan_progress.load());
return result;
@@ -2114,7 +2129,7 @@ static RPCHelpMan scantxoutset()
for (const UniValue& scanobject : request.params[1].get_array().getValues()) {
FlatSigningProvider provider;
auto scripts = EvalDescriptorStringOrObject(scanobject, provider);
- for (const auto& script : scripts) {
+ for (CScript& script : scripts) {
std::string inferred = InferDescriptor(script, provider)->ToString();
needles.emplace(script);
descriptors.emplace(std::move(script), std::move(inferred));
@@ -2133,7 +2148,7 @@ static RPCHelpMan scantxoutset()
{
ChainstateManager& chainman = EnsureChainman(node);
LOCK(cs_main);
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ Chainstate& active_chainstate = chainman.ActiveChainstate();
active_chainstate.ForceFlushStateToDisk();
pcursor = CHECK_NONFATAL(active_chainstate.CoinsDB().Cursor());
tip = CHECK_NONFATAL(active_chainstate.m_chain.Tip());
@@ -2177,7 +2192,7 @@ static RPCHelpMan getblockfilter()
"\nRetrieve a BIP 157 content filter for a particular block.\n",
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hash of the block"},
- {"filtertype", RPCArg::Type::STR, RPCArg::Default{"basic"}, "The type name of the filter"},
+ {"filtertype", RPCArg::Type::STR, RPCArg::Default{BlockFilterTypeName(BlockFilterType::BASIC)}, "The type name of the filter"},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -2192,7 +2207,7 @@ static RPCHelpMan getblockfilter()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
uint256 block_hash = ParseHashV(request.params[0], "blockhash");
- std::string filtertype_name = "basic";
+ std::string filtertype_name = BlockFilterTypeName(BlockFilterType::BASIC);
if (!request.params[1].isNull()) {
filtertype_name = request.params[1].get_str();
}
@@ -2293,7 +2308,7 @@ static RPCHelpMan dumptxoutset()
}
FILE* file{fsbridge::fopen(temppath, "wb")};
- CAutoFile afile{file, SER_DISK, CLIENT_VERSION};
+ AutoFile afile{file};
if (afile.IsNull()) {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
@@ -2313,8 +2328,8 @@ static RPCHelpMan dumptxoutset()
UniValue CreateUTXOSnapshot(
NodeContext& node,
- CChainState& chainstate,
- CAutoFile& afile,
+ Chainstate& chainstate,
+ AutoFile& afile,
const fs::path& path,
const fs::path& temppath)
{
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index 5fbd9d5fd3..6cdb5fa48b 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -20,7 +20,7 @@ extern RecursiveMutex cs_main;
class CBlock;
class CBlockIndex;
-class CChainState;
+class Chainstate;
class UniValue;
namespace node {
struct NodeContext;
@@ -54,8 +54,8 @@ void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES],
*/
UniValue CreateUTXOSnapshot(
node::NodeContext& node,
- CChainState& chainstate,
- CAutoFile& afile,
+ Chainstate& chainstate,
+ AutoFile& afile,
const fs::path& path,
const fs::path& tmppath);
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index ae0d0112ba..612dbbdacf 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -74,6 +74,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listsinceblock", 1, "target_confirmations" },
{ "listsinceblock", 2, "include_watchonly" },
{ "listsinceblock", 3, "include_removed" },
+ { "listsinceblock", 4, "include_change" },
{ "sendmany", 1, "amounts" },
{ "sendmany", 2, "minconf" },
{ "sendmany", 4, "subtractfeefrom" },
@@ -110,6 +111,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendrawtransaction", 1, "maxfeerate" },
{ "testmempoolaccept", 0, "rawtxs" },
{ "testmempoolaccept", 1, "maxfeerate" },
+ { "submitpackage", 0, "package" },
{ "combinerawtransaction", 0, "txs" },
{ "fundrawtransaction", 1, "options" },
{ "fundrawtransaction", 2, "iswitness" },
@@ -146,6 +148,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendall", 1, "conf_target" },
{ "sendall", 3, "fee_rate"},
{ "sendall", 4, "options" },
+ { "simulaterawtransaction", 0, "rawtxs" },
+ { "simulaterawtransaction", 1, "options" },
{ "importprivkey", 2, "rescan" },
{ "importaddress", 2, "rescan" },
{ "importaddress", 3, "p2sh" },
diff --git a/src/rpc/fees.cpp b/src/rpc/fees.cpp
index 1873bc1587..aa047bdea8 100644
--- a/src/rpc/fees.cpp
+++ b/src/rpc/fees.cpp
@@ -6,8 +6,6 @@
#include <core_io.h>
#include <policy/feerate.h>
#include <policy/fees.h>
-#include <policy/policy.h>
-#include <policy/settings.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <rpc/server.h>
@@ -16,7 +14,6 @@
#include <txmempool.h>
#include <univalue.h>
#include <util/fees.h>
-#include <util/system.h>
#include <algorithm>
#include <array>
@@ -89,8 +86,8 @@ static RPCHelpMan estimatesmartfee()
FeeCalculation feeCalc;
CFeeRate feeRate{fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative)};
if (feeRate != CFeeRate(0)) {
- CFeeRate min_mempool_feerate{mempool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000)};
- CFeeRate min_relay_feerate{::minRelayTxFee};
+ CFeeRate min_mempool_feerate{mempool.GetMinFee()};
+ CFeeRate min_relay_feerate{mempool.m_min_relay_feerate};
feeRate = std::max({feeRate, min_mempool_feerate, min_relay_feerate});
result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
} else {
diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp
index 97ec95a166..5c1770704d 100644
--- a/src/rpc/mempool.cpp
+++ b/src/rpc/mempool.cpp
@@ -5,8 +5,12 @@
#include <rpc/blockchain.h>
+#include <kernel/mempool_persist.h>
+
+#include <chainparams.h>
#include <core_io.h>
#include <fs.h>
+#include <node/mempool_persist_args.h>
#include <policy/rbf.h>
#include <policy/settings.h>
#include <primitives/transaction.h>
@@ -16,8 +20,12 @@
#include <txmempool.h>
#include <univalue.h>
#include <util/moneystr.h>
+#include <util/time.h>
+
+using kernel::DumpMempool;
using node::DEFAULT_MAX_RAW_TX_FEE_RATE;
+using node::MempoolPath;
using node::NodeContext;
static RPCHelpMan sendrawtransaction()
@@ -160,7 +168,7 @@ static RPCHelpMan testmempoolaccept()
NodeContext& node = EnsureAnyNodeContext(request.context);
CTxMemPool& mempool = EnsureMemPool(node);
ChainstateManager& chainman = EnsureChainman(node);
- CChainState& chainstate = chainman.ActiveChainstate();
+ Chainstate& chainstate = chainman.ActiveChainstate();
const PackageMempoolAcceptResult package_result = [&] {
LOCK(::cs_main);
if (txns.size() > 1) return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/true);
@@ -247,7 +255,7 @@ static std::vector<RPCResult> MempoolEntryDescription()
{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}},
RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction",
{RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}},
- RPCResult{RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction could be replaced due to BIP125 (replace-by-fee)"},
+ RPCResult{RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability.\n"},
RPCResult{RPCResult::Type::BOOL, "unbroadcast", "Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)"},
};
}
@@ -652,23 +660,24 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool)
// Make sure this call is atomic in the pool.
LOCK(pool.cs);
UniValue ret(UniValue::VOBJ);
- ret.pushKV("loaded", pool.IsLoaded());
+ ret.pushKV("loaded", pool.GetLoadTried());
ret.pushKV("size", (int64_t)pool.size());
ret.pushKV("bytes", (int64_t)pool.GetTotalTxSize());
ret.pushKV("usage", (int64_t)pool.DynamicMemoryUsage());
ret.pushKV("total_fee", ValueFromAmount(pool.GetTotalFee()));
- int64_t maxmempool{gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000};
- ret.pushKV("maxmempool", maxmempool);
- ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(maxmempool), ::minRelayTxFee).GetFeePerK()));
- ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
+ ret.pushKV("maxmempool", pool.m_max_size_bytes);
+ ret.pushKV("mempoolminfee", ValueFromAmount(std::max(pool.GetMinFee(), pool.m_min_relay_feerate).GetFeePerK()));
+ ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_min_relay_feerate.GetFeePerK()));
+ ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_incremental_relay_feerate.GetFeePerK()));
ret.pushKV("unbroadcastcount", uint64_t{pool.GetUnbroadcastTxs().size()});
+ ret.pushKV("fullrbf", pool.m_full_rbf);
return ret;
}
static RPCHelpMan getmempoolinfo()
{
return RPCHelpMan{"getmempoolinfo",
- "\nReturns details on the active state of the TX memory pool.\n",
+ "Returns details on the active state of the TX memory pool.",
{},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -681,7 +690,9 @@ static RPCHelpMan getmempoolinfo()
{RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"},
{RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kvB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"},
{RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"},
- {RPCResult::Type::NUM, "unbroadcastcount", "Current number of transactions that haven't passed initial broadcast yet"}
+ {RPCResult::Type::NUM, "incrementalrelayfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},
+ {RPCResult::Type::NUM, "unbroadcastcount", "Current number of transactions that haven't passed initial broadcast yet"},
+ {RPCResult::Type::BOOL, "fullrbf", "True if the mempool accepts RBF without replaceability signaling inspection"},
}},
RPCExamples{
HelpExampleCli("getmempoolinfo", "")
@@ -713,22 +724,168 @@ static RPCHelpMan savemempool()
const ArgsManager& args{EnsureAnyArgsman(request.context)};
const CTxMemPool& mempool = EnsureAnyMemPool(request.context);
- if (!mempool.IsLoaded()) {
+ if (!mempool.GetLoadTried()) {
throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
}
- if (!DumpMempool(mempool)) {
+ const fs::path& dump_path = MempoolPath(args);
+
+ if (!DumpMempool(mempool, dump_path)) {
throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
}
UniValue ret(UniValue::VOBJ);
- ret.pushKV("filename", fs::path((args.GetDataDirNet() / "mempool.dat")).u8string());
+ ret.pushKV("filename", dump_path.u8string());
return ret;
},
};
}
+static RPCHelpMan submitpackage()
+{
+ return RPCHelpMan{"submitpackage",
+ "Submit a package of raw transactions (serialized, hex-encoded) to local node (-regtest only).\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"
+ ,
+ {
+ {"package", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of raw transactions.",
+ {
+ {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
+ },
+ },
+ },
+ RPCResult{
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ_DYN, "tx-results", "transaction results keyed by wtxid",
+ {
+ {RPCResult::Type::OBJ, "wtxid", "transaction wtxid", {
+ {RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
+ {RPCResult::Type::STR_HEX, "other-wtxid", /*optional=*/true, "The wtxid of a different transaction with the same txid but different witness found in the mempool. This means the submitted transaction was ignored."},
+ {RPCResult::Type::NUM, "vsize", "Virtual transaction size as defined in BIP 141."},
+ {RPCResult::Type::OBJ, "fees", "Transaction fees", {
+ {RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT},
+ }},
+ }}
+ }},
+ {RPCResult::Type::STR_AMOUNT, "package-feerate", /*optional=*/true, "package feerate used for feerate checks in " + CURRENCY_UNIT + " per KvB. Excludes transactions which were deduplicated or accepted individually."},
+ {RPCResult::Type::ARR, "replaced-transactions", /*optional=*/true, "List of txids of replaced transactions",
+ {
+ {RPCResult::Type::STR_HEX, "", "The transaction id"},
+ }},
+ },
+ },
+ RPCExamples{
+ HelpExampleCli("testmempoolaccept", "[rawtx1, rawtx2]") +
+ HelpExampleCli("submitpackage", "[rawtx1, rawtx2]")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+ {
+ if (!Params().IsMockableChain()) {
+ throw std::runtime_error("submitpackage is for regression testing (-regtest mode) only");
+ }
+ RPCTypeCheck(request.params, {
+ UniValue::VARR,
+ });
+ 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,
+ "Array must contain between 1 and " + ToString(MAX_PACKAGE_COUNT) + " transactions.");
+ }
+
+ std::vector<CTransactionRef> txns;
+ txns.reserve(raw_transactions.size());
+ for (const auto& rawtx : raw_transactions.getValues()) {
+ CMutableTransaction mtx;
+ if (!DecodeHexTx(mtx, rawtx.get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR,
+ "TX decode failed: " + rawtx.get_str() + " Make sure the tx has at least one input.");
+ }
+ txns.emplace_back(MakeTransactionRef(std::move(mtx)));
+ }
+
+ NodeContext& node = EnsureAnyNodeContext(request.context);
+ CTxMemPool& mempool = EnsureMemPool(node);
+ Chainstate& chainstate = EnsureChainman(node).ActiveChainstate();
+ const auto package_result = WITH_LOCK(::cs_main, return ProcessNewPackage(chainstate, mempool, txns, /*test_accept=*/ false));
+
+ // First catch any errors.
+ switch(package_result.m_state.GetResult()) {
+ case PackageValidationResult::PCKG_RESULT_UNSET: break;
+ case PackageValidationResult::PCKG_POLICY:
+ {
+ throw JSONRPCTransactionError(TransactionError::INVALID_PACKAGE,
+ package_result.m_state.GetRejectReason());
+ }
+ case PackageValidationResult::PCKG_MEMPOOL_ERROR:
+ {
+ throw JSONRPCTransactionError(TransactionError::MEMPOOL_ERROR,
+ package_result.m_state.GetRejectReason());
+ }
+ case PackageValidationResult::PCKG_TX:
+ {
+ for (const auto& tx : txns) {
+ auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
+ if (it != package_result.m_tx_results.end() && it->second.m_state.IsInvalid()) {
+ throw JSONRPCTransactionError(TransactionError::MEMPOOL_REJECTED,
+ strprintf("%s failed: %s", tx->GetHash().ToString(), it->second.m_state.GetRejectReason()));
+ }
+ }
+ // If a PCKG_TX error was returned, there must have been an invalid transaction.
+ NONFATAL_UNREACHABLE();
+ }
+ }
+ for (const auto& tx : txns) {
+ size_t num_submitted{0};
+ std::string err_string;
+ const auto err = BroadcastTransaction(node, tx, err_string, 0, true, true);
+ if (err != TransactionError::OK) {
+ throw JSONRPCTransactionError(err,
+ strprintf("transaction broadcast failed: %s (all transactions were submitted, %d transactions were broadcast successfully)",
+ err_string, num_submitted));
+ }
+ }
+ UniValue rpc_result{UniValue::VOBJ};
+ UniValue tx_result_map{UniValue::VOBJ};
+ std::set<uint256> replaced_txids;
+ for (const auto& tx : txns) {
+ auto it = package_result.m_tx_results.find(tx->GetWitnessHash());
+ CHECK_NONFATAL(it != package_result.m_tx_results.end());
+ UniValue result_inner{UniValue::VOBJ};
+ result_inner.pushKV("txid", tx->GetHash().GetHex());
+ if (it->second.m_result_type == MempoolAcceptResult::ResultType::DIFFERENT_WITNESS) {
+ result_inner.pushKV("other-wtxid", it->second.m_other_wtxid.value().GetHex());
+ }
+ if (it->second.m_result_type == MempoolAcceptResult::ResultType::VALID ||
+ it->second.m_result_type == MempoolAcceptResult::ResultType::MEMPOOL_ENTRY) {
+ result_inner.pushKV("vsize", int64_t{it->second.m_vsize.value()});
+ UniValue fees(UniValue::VOBJ);
+ fees.pushKV("base", ValueFromAmount(it->second.m_base_fees.value()));
+ result_inner.pushKV("fees", fees);
+ if (it->second.m_replaced_transactions.has_value()) {
+ for (const auto& ptx : it->second.m_replaced_transactions.value()) {
+ replaced_txids.insert(ptx->GetHash());
+ }
+ }
+ }
+ tx_result_map.pushKV(tx->GetWitnessHash().GetHex(), result_inner);
+ }
+ rpc_result.pushKV("tx-results", tx_result_map);
+ if (package_result.m_package_feerate.has_value()) {
+ rpc_result.pushKV("package-feerate", ValueFromAmount(package_result.m_package_feerate.value().GetFeePerK()));
+ }
+ UniValue replaced_list(UniValue::VARR);
+ for (const uint256& hash : replaced_txids) replaced_list.push_back(hash.ToString());
+ rpc_result.pushKV("replaced-transactions", replaced_list);
+ return rpc_result;
+ },
+ };
+}
+
void RegisterMempoolRPCCommands(CRPCTable& t)
{
static const CRPCCommand commands[]{
@@ -741,6 +898,7 @@ void RegisterMempoolRPCCommands(CRPCTable& t)
{"blockchain", &getmempoolinfo},
{"blockchain", &getrawmempool},
{"blockchain", &savemempool},
+ {"hidden", &submitpackage},
};
for (const auto& c : commands) {
t.appendCommand(c.name, &c);
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index ea6db1e9a0..354af22ef4 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -132,7 +132,7 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
}
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
- if (!chainman.ProcessNewBlock(shared_pblock, true, nullptr)) {
+ if (!chainman.ProcessNewBlock(shared_pblock, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
}
@@ -476,7 +476,7 @@ static RPCHelpMan prioritisetransaction()
static UniValue BIP22ValidationResult(const BlockValidationState& state)
{
if (state.IsValid())
- return NullUniValue;
+ return UniValue::VNULL;
if (state.IsError())
throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
@@ -598,8 +598,7 @@ static RPCHelpMan getblocktemplate()
std::string strMode = "template";
UniValue lpval = NullUniValue;
std::set<std::string> setClientRules;
- int64_t nMaxVersionPreVB = -1;
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ Chainstate& active_chainstate = chainman.ActiveChainstate();
CChain& active_chain = active_chainstate.m_chain;
if (!request.params[0].isNull())
{
@@ -650,12 +649,6 @@ static RPCHelpMan getblocktemplate()
const UniValue& v = aClientRules[i];
setClientRules.insert(v.get_str());
}
- } else {
- // NOTE: It is important that this NOT be read if versionbits is supported
- const UniValue& uvMaxVersion = find_value(oparam, "maxversion");
- if (uvMaxVersion.isNum()) {
- nMaxVersionPreVB = uvMaxVersion.getInt<int64_t>();
- }
}
}
@@ -686,7 +679,7 @@ static RPCHelpMan getblocktemplate()
if (lpval.isStr())
{
// Format: <hashBestChain><nTransactionsUpdatedLast>
- std::string lpstr = lpval.get_str();
+ const std::string& lpstr = lpval.get_str();
hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
nTransactionsUpdatedLastLP = LocaleIndependentAtoi<int64_t>(lpstr.substr(64));
@@ -863,7 +856,6 @@ static RPCHelpMan getblocktemplate()
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
// Not supported by the client; make sure it's safe to proceed
if (!vbinfo.gbt_force) {
- // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
}
}
@@ -876,14 +868,6 @@ static RPCHelpMan getblocktemplate()
result.pushKV("vbavailable", vbavailable);
result.pushKV("vbrequired", int(0));
- if (nMaxVersionPreVB >= 2) {
- // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here
- // Because BIP 34 changed how the generation transaction is serialized, we can only use version/force back to v2 blocks
- // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated
- // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated
- aMutable.push_back("version/force");
- }
-
result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
result.pushKV("transactions", transactions);
result.pushKV("coinbaseaux", aux);
@@ -997,7 +981,7 @@ static RPCHelpMan submitblock()
bool new_block;
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
RegisterSharedValidationInterface(sc);
- bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*new_block=*/&new_block);
+ bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
UnregisterSharedValidationInterface(sc);
if (!new_block && accepted) {
return "duplicate";
@@ -1039,8 +1023,8 @@ static RPCHelpMan submitheader()
}
BlockValidationState state;
- chainman.ProcessNewBlockHeaders({h}, state);
- if (state.IsValid()) return NullUniValue;
+ chainman.ProcessNewBlockHeaders({h}, /*min_pow_checked=*/true, state);
+ if (state.IsValid()) return UniValue::VNULL;
if (state.IsError()) {
throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString());
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 0a061f2451..d701a180ab 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -23,6 +23,7 @@
#include <timedata.h>
#include <util/strencodings.h>
#include <util/string.h>
+#include <util/time.h>
#include <util/translation.h>
#include <validation.h>
#include <version.h>
@@ -60,7 +61,7 @@ static RPCHelpMan getconnectioncount()
NodeContext& node = EnsureAnyNodeContext(request.context);
const CConnman& connman = EnsureConnman(node);
- return (int)connman.GetNodeCount(ConnectionDirection::Both);
+ return connman.GetNodeCount(ConnectionDirection::Both);
},
};
}
@@ -84,7 +85,7 @@ static RPCHelpMan ping()
// Request that each node send a ping during next message processing pass
peerman.SendPings();
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -131,6 +132,7 @@ static RPCHelpMan getpeerinfo()
{RPCResult::Type::BOOL, "bip152_hb_to", "Whether we selected peer as (compact blocks) high-bandwidth peer"},
{RPCResult::Type::BOOL, "bip152_hb_from", "Whether peer selected us as (compact blocks) high-bandwidth peer"},
{RPCResult::Type::NUM, "startingheight", /*optional=*/true, "The starting height (block) of the peer"},
+ {RPCResult::Type::NUM, "presynced_headers", /*optional=*/true, "The current height of header pre-synchronization with this peer, or -1 if no low-work sync is in progress"},
{RPCResult::Type::NUM, "synced_headers", /*optional=*/true, "The last header we have in common with this peer"},
{RPCResult::Type::NUM, "synced_blocks", /*optional=*/true, "The last block we have in common with this peer"},
{RPCResult::Type::ARR, "inflight", /*optional=*/true, "",
@@ -195,8 +197,9 @@ static RPCHelpMan getpeerinfo()
if (stats.m_mapped_as != 0) {
obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
}
- obj.pushKV("services", strprintf("%016x", stats.nServices));
- obj.pushKV("servicesnames", GetServicesNames(stats.nServices));
+ ServiceFlags services{fStateStats ? statestats.their_services : ServiceFlags::NODE_NONE};
+ obj.pushKV("services", strprintf("%016x", services));
+ obj.pushKV("servicesnames", GetServicesNames(services));
obj.pushKV("lastsend", count_seconds(stats.m_last_send));
obj.pushKV("lastrecv", count_seconds(stats.m_last_recv));
obj.pushKV("last_transaction", count_seconds(stats.m_last_tx_time));
@@ -206,13 +209,13 @@ static RPCHelpMan getpeerinfo()
obj.pushKV("conntime", count_seconds(stats.m_connected));
obj.pushKV("timeoffset", stats.nTimeOffset);
if (stats.m_last_ping_time > 0us) {
- obj.pushKV("pingtime", CountSecondsDouble(stats.m_last_ping_time));
+ obj.pushKV("pingtime", Ticks<SecondsDouble>(stats.m_last_ping_time));
}
if (stats.m_min_ping_time < std::chrono::microseconds::max()) {
- obj.pushKV("minping", CountSecondsDouble(stats.m_min_ping_time));
+ obj.pushKV("minping", Ticks<SecondsDouble>(stats.m_min_ping_time));
}
if (fStateStats && statestats.m_ping_wait > 0s) {
- obj.pushKV("pingwait", CountSecondsDouble(statestats.m_ping_wait));
+ obj.pushKV("pingwait", Ticks<SecondsDouble>(statestats.m_ping_wait));
}
obj.pushKV("version", stats.nVersion);
// Use the sanitized form of subver here, to avoid tricksy remote peers from
@@ -224,6 +227,7 @@ static RPCHelpMan getpeerinfo()
obj.pushKV("bip152_hb_from", stats.m_bip152_highbandwidth_from);
if (fStateStats) {
obj.pushKV("startingheight", statestats.m_starting_height);
+ obj.pushKV("presynced_headers", statestats.presync_height);
obj.pushKV("synced_headers", statestats.nSyncHeight);
obj.pushKV("synced_blocks", statestats.nCommonHeight);
UniValue heights(UniValue::VARR);
@@ -238,7 +242,7 @@ static RPCHelpMan getpeerinfo()
obj.pushKV("addr_rate_limited", statestats.m_addr_rate_limited);
}
UniValue permissions(UniValue::VARR);
- for (const auto& permission : NetPermissions::ToStrings(stats.m_permissionFlags)) {
+ for (const auto& permission : NetPermissions::ToStrings(stats.m_permission_flags)) {
permissions.push_back(permission);
}
obj.pushKV("permissions", permissions);
@@ -303,7 +307,7 @@ static RPCHelpMan addnode()
{
CAddress addr;
connman.OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), ConnectionType::MANUAL);
- return NullUniValue;
+ return UniValue::VNULL;
}
if (strCommand == "add")
@@ -319,7 +323,7 @@ static RPCHelpMan addnode()
}
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -422,7 +426,7 @@ static RPCHelpMan disconnectnode()
throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes");
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -603,7 +607,7 @@ static RPCHelpMan getnetworkinfo()
}},
}},
{RPCResult::Type::NUM, "relayfee", "minimum relay fee rate for transactions in " + CURRENCY_UNIT + "/kvB"},
- {RPCResult::Type::NUM, "incrementalfee", "minimum fee rate increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kvB"},
+ {RPCResult::Type::NUM, "incrementalfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"},
{RPCResult::Type::ARR, "localaddresses", "list of local addresses",
{
{RPCResult::Type::OBJ, "", "",
@@ -639,13 +643,16 @@ static RPCHelpMan getnetworkinfo()
obj.pushKV("timeoffset", GetTimeOffset());
if (node.connman) {
obj.pushKV("networkactive", node.connman->GetNetworkActive());
- obj.pushKV("connections", (int)node.connman->GetNodeCount(ConnectionDirection::Both));
- obj.pushKV("connections_in", (int)node.connman->GetNodeCount(ConnectionDirection::In));
- obj.pushKV("connections_out", (int)node.connman->GetNodeCount(ConnectionDirection::Out));
+ obj.pushKV("connections", node.connman->GetNodeCount(ConnectionDirection::Both));
+ obj.pushKV("connections_in", node.connman->GetNodeCount(ConnectionDirection::In));
+ obj.pushKV("connections_out", node.connman->GetNodeCount(ConnectionDirection::Out));
}
obj.pushKV("networks", GetNetworksInfo());
- obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
- obj.pushKV("incrementalfee", ValueFromAmount(::incrementalRelayFee.GetFeePerK()));
+ if (node.mempool) {
+ // Those fields can be deprecated, to be replaced by the getmempoolinfo fields
+ obj.pushKV("relayfee", ValueFromAmount(node.mempool->m_min_relay_feerate.GetFeePerK()));
+ obj.pushKV("incrementalfee", ValueFromAmount(node.mempool->m_incremental_relay_feerate.GetFeePerK()));
+ }
UniValue localAddresses(UniValue::VARR);
{
LOCK(g_maplocalhost_mutex);
@@ -744,7 +751,7 @@ static RPCHelpMan setban()
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously manually banned.");
}
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -818,7 +825,7 @@ static RPCHelpMan clearbanned()
node.banman->ClearBanned();
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -893,7 +900,7 @@ static RPCHelpMan getnodeaddresses()
for (const CAddress& addr : vAddr) {
UniValue obj(UniValue::VOBJ);
- obj.pushKV("time", (int)addr.nTime);
+ obj.pushKV("time", int64_t{TicksSinceEpoch<std::chrono::seconds>(addr.nTime)});
obj.pushKV("services", (uint64_t)addr.nServices);
obj.pushKV("address", addr.ToStringIP());
obj.pushKV("port", addr.GetPort());
@@ -940,8 +947,9 @@ static RPCHelpMan addpeeraddress()
bool success{false};
if (LookupHost(addr_string, net_addr, false)) {
- CAddress address{{net_addr, port}, ServiceFlags{NODE_NETWORK | NODE_WITNESS}};
- address.nTime = GetAdjustedTime();
+ CService service{net_addr, port};
+ CAddress address{MaybeFlipIPv6toCJDNS(service), ServiceFlags{NODE_NETWORK | NODE_WITNESS}};
+ address.nTime = Now<NodeSeconds>();
// The source address is set equal to the address. This is equivalent to the peer
// announcing itself.
if (node.addrman->Add({address}, address)) {
diff --git a/src/rpc/node.cpp b/src/rpc/node.cpp
index 5475662b82..605ebc15a7 100644
--- a/src/rpc/node.cpp
+++ b/src/rpc/node.cpp
@@ -65,7 +65,7 @@ static RPCHelpMan setmocktime()
}
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -85,7 +85,7 @@ static RPCHelpMan invokedisallowedsyscall()
throw std::runtime_error("invokedisallowedsyscall is used for testing only.");
}
TestDisallowedSandboxCall();
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -118,7 +118,7 @@ static RPCHelpMan mockscheduler()
CHECK_NONFATAL(node_context->scheduler);
node_context->scheduler->MockForward(std::chrono::seconds(delta_seconds));
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
diff --git a/src/rpc/output_script.cpp b/src/rpc/output_script.cpp
index f4bb76f50f..a980c609e8 100644
--- a/src/rpc/output_script.cpp
+++ b/src/rpc/output_script.cpp
@@ -26,11 +26,6 @@
#include <tuple>
#include <vector>
-namespace node {
-struct NodeContext;
-}
-using node::NodeContext;
-
static RPCHelpMan validateaddress()
{
return RPCHelpMan{
@@ -278,7 +273,7 @@ static RPCHelpMan deriveaddresses()
UniValue addresses(UniValue::VARR);
- for (int i = range_begin; i <= range_end; ++i) {
+ for (int64_t i = range_begin; i <= range_end; ++i) {
FlatSigningProvider provider;
std::vector<CScript> scripts;
if (!desc->Expand(i, key_provider, scripts, provider)) {
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index b9b8c36bb3..d654de1862 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -46,14 +46,12 @@
#include <univalue.h>
using node::AnalyzePSBT;
-using node::BroadcastTransaction;
using node::FindCoins;
using node::GetTransaction;
using node::NodeContext;
using node::PSBTAnalysis;
-using node::ReadBlockFromDisk;
-static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, CChainState& active_chainstate)
+static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, Chainstate& active_chainstate)
{
// Call into TxToUniv() in bitcoin-common to decode the transaction hex.
//
@@ -98,8 +96,8 @@ static std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc)
{RPCResult::Type::NUM, "vout", /*optional=*/true, "The output number (if not coinbase transaction)"},
{RPCResult::Type::OBJ, "scriptSig", /*optional=*/true, "The script (if not coinbase transaction)",
{
- {RPCResult::Type::STR, "asm", "asm"},
- {RPCResult::Type::STR_HEX, "hex", "hex"},
+ {RPCResult::Type::STR, "asm", "Disassembly of the signature script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw signature script bytes, hex-encoded"},
}},
{RPCResult::Type::ARR, "txinwitness", /*optional=*/true, "",
{
@@ -116,9 +114,9 @@ static std::vector<RPCResult> DecodeTxDoc(const std::string& txid_field_doc)
{RPCResult::Type::NUM, "n", "index"},
{RPCResult::Type::OBJ, "scriptPubKey", "",
{
- {RPCResult::Type::STR, "asm", "the asm"},
+ {RPCResult::Type::STR, "asm", "Disassembly of the public key script"},
{RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
- {RPCResult::Type::STR_HEX, "hex", "the hex"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw public key script bytes, hex-encoded"},
{RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
{RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
}},
@@ -159,7 +157,7 @@ static std::vector<RPCArg> CreateTxDoc()
},
},
{"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
- {"replaceable", RPCArg::Type::BOOL, RPCArg::Default{false}, "Marks this transaction as BIP125-replaceable.\n"
+ {"replaceable", RPCArg::Type::BOOL, RPCArg::Default{true}, "Marks this transaction as BIP125-replaceable.\n"
"Allows this transaction to be replaced by a transaction with higher fees. If provided, it is an error if explicit sequence numbers are incompatible."},
};
}
@@ -304,7 +302,7 @@ static RPCHelpMan createrawtransaction()
}, true
);
- bool rbf = false;
+ std::optional<bool> rbf;
if (!request.params[3].isNull()) {
rbf = request.params[3].isTrue();
}
@@ -680,6 +678,200 @@ static RPCHelpMan signrawtransactionwithkey()
};
}
+const RPCResult decodepsbt_inputs{
+ RPCResult::Type::ARR, "inputs", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ, "non_witness_utxo", /*optional=*/true, "Decoded network transaction for non-witness UTXOs",
+ {
+ {RPCResult::Type::ELISION, "",""},
+ }},
+ {RPCResult::Type::OBJ, "witness_utxo", /*optional=*/true, "Transaction output for witness UTXOs",
+ {
+ {RPCResult::Type::NUM, "amount", "The value in " + CURRENCY_UNIT},
+ {RPCResult::Type::OBJ, "scriptPubKey", "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the public key script"},
+ {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw public key script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
+ }},
+ }},
+ {RPCResult::Type::OBJ_DYN, "partial_signatures", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."},
+ }},
+ {RPCResult::Type::STR, "sighash", /*optional=*/true, "The sighash type to be used"},
+ {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the redeem script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw redeem script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ }},
+ {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the witness script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ }},
+ {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The public key with the derivation path as the value."},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ }},
+ }},
+ {RPCResult::Type::OBJ, "final_scriptSig", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the final signature script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw final signature script bytes, hex-encoded"},
+ }},
+ {RPCResult::Type::ARR, "final_scriptwitness", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"},
+ }},
+ {RPCResult::Type::OBJ_DYN, "ripemd160_preimages", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
+ }},
+ {RPCResult::Type::OBJ_DYN, "sha256_preimages", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
+ }},
+ {RPCResult::Type::OBJ_DYN, "hash160_preimages", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
+ }},
+ {RPCResult::Type::OBJ_DYN, "hash256_preimages", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
+ }},
+ {RPCResult::Type::STR_HEX, "taproot_key_path_sig", /*optional=*/ true, "hex-encoded signature for the Taproot key path spend"},
+ {RPCResult::Type::ARR, "taproot_script_path_sigs", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::OBJ, "signature", /*optional=*/ true, "The signature for the pubkey and leaf hash combination",
+ {
+ {RPCResult::Type::STR, "pubkey", "The x-only pubkey for this signature"},
+ {RPCResult::Type::STR, "leaf_hash", "The leaf hash for this signature"},
+ {RPCResult::Type::STR, "sig", "The signature itself"},
+ }},
+ }},
+ {RPCResult::Type::ARR, "taproot_scripts", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "script", "A leaf script"},
+ {RPCResult::Type::NUM, "leaf_ver", "The version number for the leaf script"},
+ {RPCResult::Type::ARR, "control_blocks", "The control blocks for this script",
+ {
+ {RPCResult::Type::STR_HEX, "control_block", "A hex-encoded control block for this script"},
+ }},
+ }},
+ }},
+ {RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ {RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
+ }},
+ }},
+ }},
+ {RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
+ {RPCResult::Type::STR_HEX, "taproot_merkle_root", /*optional=*/ true, "The hex-encoded Taproot merkle root"},
+ {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/ true, "The unknown input fields",
+ {
+ {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
+ }},
+ {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The input proprietary map",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
+ {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
+ {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
+ {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
+ }},
+ }},
+ }},
+ }
+};
+
+const RPCResult decodepsbt_outputs{
+ RPCResult::Type::ARR, "outputs", "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the redeem script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw redeem script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ }},
+ {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
+ {
+ {RPCResult::Type::STR, "asm", "Disassembly of the witness script"},
+ {RPCResult::Type::STR_HEX, "hex", "The raw witness script bytes, hex-encoded"},
+ {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
+ }},
+ {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ }},
+ }},
+ {RPCResult::Type::STR_HEX, "taproot_internal_key", /*optional=*/ true, "The hex-encoded Taproot x-only internal key"},
+ {RPCResult::Type::ARR, "taproot_tree", /*optional=*/ true, "The tuples that make up the Taproot tree, in depth first search order",
+ {
+ {RPCResult::Type::OBJ, "tuple", /*optional=*/ true, "A single leaf script in the taproot tree",
+ {
+ {RPCResult::Type::NUM, "depth", "The depth of this element in the tree"},
+ {RPCResult::Type::NUM, "leaf_ver", "The version of this leaf"},
+ {RPCResult::Type::STR, "script", "The hex-encoded script itself"},
+ }},
+ }},
+ {RPCResult::Type::ARR, "taproot_bip32_derivs", /*optional=*/ true, "",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "pubkey", "The x-only public key this path corresponds to"},
+ {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
+ {RPCResult::Type::STR, "path", "The path"},
+ {RPCResult::Type::ARR, "leaf_hashes", "The hashes of the leaves this pubkey appears in",
+ {
+ {RPCResult::Type::STR_HEX, "hash", "The hash of a leaf this pubkey appears in"},
+ }},
+ }},
+ }},
+ {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown output fields",
+ {
+ {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
+ }},
+ {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The output proprietary map",
+ {
+ {RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
+ {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
+ {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
+ {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
+ }},
+ }},
+ }},
+ }
+};
+
static RPCHelpMan decodepsbt()
{
return RPCHelpMan{
@@ -719,134 +911,8 @@ static RPCHelpMan decodepsbt()
{
{RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
}},
- {RPCResult::Type::ARR, "inputs", "",
- {
- {RPCResult::Type::OBJ, "", "",
- {
- {RPCResult::Type::OBJ, "non_witness_utxo", /*optional=*/true, "Decoded network transaction for non-witness UTXOs",
- {
- {RPCResult::Type::ELISION, "",""},
- }},
- {RPCResult::Type::OBJ, "witness_utxo", /*optional=*/true, "Transaction output for witness UTXOs",
- {
- {RPCResult::Type::NUM, "amount", "The value in " + CURRENCY_UNIT},
- {RPCResult::Type::OBJ, "scriptPubKey", "",
- {
- {RPCResult::Type::STR, "asm", "The asm"},
- {RPCResult::Type::STR, "desc", "Inferred descriptor for the output"},
- {RPCResult::Type::STR_HEX, "hex", "The hex"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- {RPCResult::Type::STR, "address", /*optional=*/true, "The Bitcoin address (only if a well-defined address exists)"},
- }},
- }},
- {RPCResult::Type::OBJ_DYN, "partial_signatures", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."},
- }},
- {RPCResult::Type::STR, "sighash", /*optional=*/true, "The sighash type to be used"},
- {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "The asm"},
- {RPCResult::Type::STR_HEX, "hex", "The hex"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- }},
- {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "The asm"},
- {RPCResult::Type::STR_HEX, "hex", "The hex"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- }},
- {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
- {
- {RPCResult::Type::OBJ, "", "",
- {
- {RPCResult::Type::STR, "pubkey", "The public key with the derivation path as the value."},
- {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
- {RPCResult::Type::STR, "path", "The path"},
- }},
- }},
- {RPCResult::Type::OBJ, "final_scriptSig", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "The asm"},
- {RPCResult::Type::STR, "hex", "The hex"},
- }},
- {RPCResult::Type::ARR, "final_scriptwitness", /*optional=*/true, "",
- {
- {RPCResult::Type::STR_HEX, "", "hex-encoded witness data (if any)"},
- }},
- {RPCResult::Type::OBJ_DYN, "ripemd160_preimages", /*optional=*/ true, "",
- {
- {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
- }},
- {RPCResult::Type::OBJ_DYN, "sha256_preimages", /*optional=*/ true, "",
- {
- {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
- }},
- {RPCResult::Type::OBJ_DYN, "hash160_preimages", /*optional=*/ true, "",
- {
- {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
- }},
- {RPCResult::Type::OBJ_DYN, "hash256_preimages", /*optional=*/ true, "",
- {
- {RPCResult::Type::STR, "hash", "The hash and preimage that corresponds to it."},
- }},
- {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/ true, "The unknown input fields",
- {
- {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
- }},
- {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The input proprietary map",
- {
- {RPCResult::Type::OBJ, "", "",
- {
- {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
- {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
- {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
- {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
- }},
- }},
- }},
- }},
- {RPCResult::Type::ARR, "outputs", "",
- {
- {RPCResult::Type::OBJ, "", "",
- {
- {RPCResult::Type::OBJ, "redeem_script", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "The asm"},
- {RPCResult::Type::STR_HEX, "hex", "The hex"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- }},
- {RPCResult::Type::OBJ, "witness_script", /*optional=*/true, "",
- {
- {RPCResult::Type::STR, "asm", "The asm"},
- {RPCResult::Type::STR_HEX, "hex", "The hex"},
- {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"},
- }},
- {RPCResult::Type::ARR, "bip32_derivs", /*optional=*/true, "",
- {
- {RPCResult::Type::OBJ, "", "",
- {
- {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"},
- {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"},
- {RPCResult::Type::STR, "path", "The path"},
- }},
- }},
- {RPCResult::Type::OBJ_DYN, "unknown", /*optional=*/true, "The unknown global fields",
- {
- {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"},
- }},
- {RPCResult::Type::ARR, "proprietary", /*optional=*/true, "The output proprietary map",
- {
- {RPCResult::Type::OBJ, "", "",
- {
- {RPCResult::Type::STR_HEX, "identifier", "The hex string for the proprietary identifier"},
- {RPCResult::Type::NUM, "subtype", "The number for the subtype"},
- {RPCResult::Type::STR_HEX, "key", "The hex for the key"},
- {RPCResult::Type::STR_HEX, "value", "The hex for the value"},
- }},
- }},
- }},
- }},
+ decodepsbt_inputs,
+ decodepsbt_outputs,
{RPCResult::Type::STR_AMOUNT, "fee", /*optional=*/true, "The transaction fee paid if all UTXOs slots in the PSBT have been filled."},
}
},
@@ -1045,6 +1111,72 @@ static RPCHelpMan decodepsbt()
in.pushKV("hash256_preimages", hash256_preimages);
}
+ // Taproot key path signature
+ if (!input.m_tap_key_sig.empty()) {
+ in.pushKV("taproot_key_path_sig", HexStr(input.m_tap_key_sig));
+ }
+
+ // Taproot script path signatures
+ if (!input.m_tap_script_sigs.empty()) {
+ UniValue script_sigs(UniValue::VARR);
+ for (const auto& [pubkey_leaf, sig] : input.m_tap_script_sigs) {
+ const auto& [xonly, leaf_hash] = pubkey_leaf;
+ UniValue sigobj(UniValue::VOBJ);
+ sigobj.pushKV("pubkey", HexStr(xonly));
+ sigobj.pushKV("leaf_hash", HexStr(leaf_hash));
+ sigobj.pushKV("sig", HexStr(sig));
+ script_sigs.push_back(sigobj);
+ }
+ in.pushKV("taproot_script_path_sigs", script_sigs);
+ }
+
+ // Taproot leaf scripts
+ if (!input.m_tap_scripts.empty()) {
+ UniValue tap_scripts(UniValue::VARR);
+ for (const auto& [leaf, control_blocks] : input.m_tap_scripts) {
+ const auto& [script, leaf_ver] = leaf;
+ UniValue script_info(UniValue::VOBJ);
+ script_info.pushKV("script", HexStr(script));
+ script_info.pushKV("leaf_ver", leaf_ver);
+ UniValue control_blocks_univ(UniValue::VARR);
+ for (const auto& control_block : control_blocks) {
+ control_blocks_univ.push_back(HexStr(control_block));
+ }
+ script_info.pushKV("control_blocks", control_blocks_univ);
+ tap_scripts.push_back(script_info);
+ }
+ in.pushKV("taproot_scripts", tap_scripts);
+ }
+
+ // Taproot bip32 keypaths
+ if (!input.m_tap_bip32_paths.empty()) {
+ UniValue keypaths(UniValue::VARR);
+ for (const auto& [xonly, leaf_origin] : input.m_tap_bip32_paths) {
+ const auto& [leaf_hashes, origin] = leaf_origin;
+ UniValue path_obj(UniValue::VOBJ);
+ path_obj.pushKV("pubkey", HexStr(xonly));
+ path_obj.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(origin.fingerprint)));
+ path_obj.pushKV("path", WriteHDKeypath(origin.path));
+ UniValue leaf_hashes_arr(UniValue::VARR);
+ for (const auto& leaf_hash : leaf_hashes) {
+ leaf_hashes_arr.push_back(HexStr(leaf_hash));
+ }
+ path_obj.pushKV("leaf_hashes", leaf_hashes_arr);
+ keypaths.push_back(path_obj);
+ }
+ in.pushKV("taproot_bip32_derivs", keypaths);
+ }
+
+ // Taproot internal key
+ if (!input.m_tap_internal_key.IsNull()) {
+ in.pushKV("taproot_internal_key", HexStr(input.m_tap_internal_key));
+ }
+
+ // Write taproot merkle root
+ if (!input.m_tap_merkle_root.IsNull()) {
+ in.pushKV("taproot_merkle_root", HexStr(input.m_tap_merkle_root));
+ }
+
// Proprietary
if (!input.m_proprietary.empty()) {
UniValue proprietary(UniValue::VARR);
@@ -1103,6 +1235,43 @@ static RPCHelpMan decodepsbt()
out.pushKV("bip32_derivs", keypaths);
}
+ // Taproot internal key
+ if (!output.m_tap_internal_key.IsNull()) {
+ out.pushKV("taproot_internal_key", HexStr(output.m_tap_internal_key));
+ }
+
+ // Taproot tree
+ if (!output.m_tap_tree.empty()) {
+ UniValue tree(UniValue::VARR);
+ for (const auto& [depth, leaf_ver, script] : output.m_tap_tree) {
+ UniValue elem(UniValue::VOBJ);
+ elem.pushKV("depth", (int)depth);
+ elem.pushKV("leaf_ver", (int)leaf_ver);
+ elem.pushKV("script", HexStr(script));
+ tree.push_back(elem);
+ }
+ out.pushKV("taproot_tree", tree);
+ }
+
+ // Taproot bip32 keypaths
+ if (!output.m_tap_bip32_paths.empty()) {
+ UniValue keypaths(UniValue::VARR);
+ for (const auto& [xonly, leaf_origin] : output.m_tap_bip32_paths) {
+ const auto& [leaf_hashes, origin] = leaf_origin;
+ UniValue path_obj(UniValue::VOBJ);
+ path_obj.pushKV("pubkey", HexStr(xonly));
+ path_obj.pushKV("master_fingerprint", strprintf("%08x", ReadBE32(origin.fingerprint)));
+ path_obj.pushKV("path", WriteHDKeypath(origin.path));
+ UniValue leaf_hashes_arr(UniValue::VARR);
+ for (const auto& leaf_hash : leaf_hashes) {
+ leaf_hashes_arr.push_back(HexStr(leaf_hash));
+ }
+ path_obj.pushKV("leaf_hashes", leaf_hashes_arr);
+ keypaths.push_back(path_obj);
+ }
+ out.pushKV("taproot_bip32_derivs", keypaths);
+ }
+
// Proprietary
if (!output.m_proprietary.empty()) {
UniValue proprietary(UniValue::VARR);
@@ -1278,7 +1447,7 @@ static RPCHelpMan createpsbt()
}, true
);
- bool rbf = false;
+ std::optional<bool> rbf;
if (!request.params[3].isNull()) {
rbf = request.params[3].isTrue();
}
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index 86b5b7e960..b078ee8b29 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -21,7 +21,7 @@
#include <util/strencodings.h>
#include <util/translation.h>
-CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, bool rbf)
+CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, std::optional<bool> rbf)
{
if (outputs_in.isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, output argument must be non-null");
@@ -60,7 +60,8 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
uint32_t nSequence;
- if (rbf) {
+
+ if (rbf.value_or(true)) {
nSequence = MAX_BIP125_RBF_SEQUENCE; /* CTxIn::SEQUENCE_FINAL - 2 */
} else if (rawTx.nLockTime) {
nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; /* CTxIn::SEQUENCE_FINAL - 1 */
@@ -132,7 +133,7 @@ CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniVal
}
}
- if (rbf && rawTx.vin.size() > 0 && !SignalsOptInRBF(CTransaction(rawTx))) {
+ if (rbf.has_value() && rbf.value() && rawTx.vin.size() > 0 && !SignalsOptInRBF(CTransaction(rawTx))) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter combination: Sequence number(s) contradict replaceable option");
}
@@ -159,14 +160,14 @@ static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::
void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins)
{
if (!prevTxsUnival.isNull()) {
- UniValue prevTxs = prevTxsUnival.get_array();
+ const UniValue& prevTxs = prevTxsUnival.get_array();
for (unsigned int idx = 0; idx < prevTxs.size(); ++idx) {
const UniValue& p = prevTxs[idx];
if (!p.isObject()) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
}
- UniValue prevOut = p.get_obj();
+ const UniValue& prevOut = p.get_obj();
RPCTypeCheckObj(prevOut,
{
diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
index c3eb1417f8..9b5c9f08d4 100644
--- a/src/rpc/rawtransaction_util.h
+++ b/src/rpc/rawtransaction_util.h
@@ -7,6 +7,7 @@
#include <map>
#include <string>
+#include <optional>
struct bilingual_str;
class FillableSigningProvider;
@@ -38,6 +39,6 @@ void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const
void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins);
/** Create a transaction from univalue parameters */
-CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, bool rbf);
+CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime, std::optional<bool> rbf);
#endif // BITCOIN_RPC_RAWTRANSACTION_UTIL_H
diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp
index 304c265b31..8595fa78bb 100644
--- a/src/rpc/request.cpp
+++ b/src/rpc/request.cpp
@@ -66,16 +66,16 @@ UniValue JSONRPCError(int code, const std::string& message)
*/
static const std::string COOKIEAUTH_USER = "__cookie__";
/** Default name for auth cookie file */
-static const std::string COOKIEAUTH_FILE = ".cookie";
+static const char* const COOKIEAUTH_FILE = ".cookie";
/** Get name of RPC authentication cookie file */
static fs::path GetAuthCookieFile(bool temp=false)
{
- std::string arg = gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE);
+ fs::path arg = gArgs.GetPathArg("-rpccookiefile", COOKIEAUTH_FILE);
if (temp) {
arg += ".tmp";
}
- return AbsPathForConfigVal(fs::PathFromString(arg));
+ return AbsPathForConfigVal(arg);
}
bool GenerateAuthCookie(std::string *cookie_out)
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 66ed18045e..83a352dbea 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -11,11 +11,13 @@
#include <util/strencodings.h>
#include <util/string.h>
#include <util/system.h>
+#include <util/time.h>
#include <boost/signals2/signal.hpp>
#include <cassert>
-#include <memory> // for unique_ptr
+#include <chrono>
+#include <memory>
#include <mutex>
#include <unordered_map>
@@ -33,7 +35,7 @@ static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& req
struct RPCCommandExecutionInfo
{
std::string method;
- int64_t start;
+ SteadyClock::time_point start;
};
struct RPCServerInfo
@@ -50,7 +52,7 @@ struct RPCCommandExecution
explicit RPCCommandExecution(const std::string& method)
{
LOCK(g_rpc_server_info.mutex);
- it = g_rpc_server_info.active_commands.insert(g_rpc_server_info.active_commands.end(), {method, GetTimeMicros()});
+ it = g_rpc_server_info.active_commands.insert(g_rpc_server_info.active_commands.end(), {method, SteadyClock::now()});
}
~RPCCommandExecution()
{
@@ -231,7 +233,7 @@ static RPCHelpMan getrpcinfo()
for (const RPCCommandExecutionInfo& info : g_rpc_server_info.active_commands) {
UniValue entry(UniValue::VOBJ);
entry.pushKV("method", info.method);
- entry.pushKV("duration", GetTimeMicros() - info.start);
+ entry.pushKV("duration", int64_t{Ticks<std::chrono::microseconds>(SteadyClock::now() - info.start)});
active_commands.push_back(entry);
}
diff --git a/src/rpc/txoutproof.cpp b/src/rpc/txoutproof.cpp
index dcf6c6bee1..cd8b49bfe1 100644
--- a/src/rpc/txoutproof.cpp
+++ b/src/rpc/txoutproof.cpp
@@ -66,7 +66,7 @@ static RPCHelpMan gettxoutproof()
}
} else {
LOCK(cs_main);
- CChainState& active_chainstate = chainman.ActiveChainstate();
+ Chainstate& active_chainstate = chainman.ActiveChainstate();
// Loop through txids and try to find which block they're in. Exit loop once a block is found.
for (const auto& tx : setTxids) {
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 7517f64ea1..43935650fa 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -50,7 +50,8 @@ void RPCTypeCheck(const UniValue& params,
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
{
if (!typeExpected.typeAny && value.type() != typeExpected.type) {
- throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected.type), uvTypeName(value.type())));
+ throw JSONRPCError(RPC_TYPE_ERROR,
+ strprintf("JSON value of type %s is not of expected type %s", uvTypeName(value.type()), uvTypeName(typeExpected.type)));
}
}
@@ -98,7 +99,7 @@ CAmount AmountFromValue(const UniValue& value, int decimals)
uint256 ParseHashV(const UniValue& v, std::string strName)
{
- std::string strHex(v.get_str());
+ const std::string& strHex(v.get_str());
if (64 != strHex.length())
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d, for '%s')", strName, 64, strHex.length(), strHex));
if (!IsHex(strHex)) // Note: IsHex("") is false
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index cece0b60ce..864eb8864f 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -6,6 +6,7 @@
#include <key_io.h>
#include <pubkey.h>
+#include <script/miniscript.h>
#include <script/script.h>
#include <script/standard.h>
@@ -161,6 +162,20 @@ public:
virtual ~PubkeyProvider() = default;
+ /** Compare two public keys represented by this provider.
+ * Used by the Miniscript descriptors to check for duplicate keys in the script.
+ */
+ bool operator<(PubkeyProvider& other) const {
+ CPubKey a, b;
+ SigningProvider dummy;
+ KeyOriginInfo dummy_info;
+
+ GetPubKey(0, dummy, a, dummy_info);
+ other.GetPubKey(0, dummy, b, dummy_info);
+
+ return a < b;
+ }
+
/** Derive a public key.
* read_cache is the cache to read keys from (if not nullptr)
* write_cache is the cache to write keys to (if not nullptr)
@@ -313,7 +328,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
{
if (!GetExtKey(arg, xprv)) return false;
for (auto entry : m_path) {
- xprv.Derive(xprv, entry);
+ if (!xprv.Derive(xprv, entry)) return false;
if (entry >> 31) {
last_hardened = xprv;
}
@@ -373,14 +388,13 @@ public:
}
} else {
for (auto entry : m_path) {
- der = parent_extkey.Derive(parent_extkey, entry);
- assert(der);
+ if (!parent_extkey.Derive(parent_extkey, entry)) return false;
}
final_extkey = parent_extkey;
if (m_derive == DeriveType::UNHARDENED) der = parent_extkey.Derive(final_extkey, pos);
assert(m_derive != DeriveType::HARDENED);
}
- assert(der);
+ if (!der) return false;
final_info_out = final_info_out_tmp;
key_out = final_extkey.pubkey;
@@ -483,8 +497,8 @@ public:
CExtKey extkey;
CExtKey dummy;
if (!GetDerivedExtKey(arg, extkey, dummy)) return false;
- if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
- if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
+ if (m_derive == DeriveType::UNHARDENED && !extkey.Derive(extkey, pos)) return false;
+ if (m_derive == DeriveType::HARDENED && !extkey.Derive(extkey, pos | 0x80000000UL)) return false;
key = extkey.key;
return true;
}
@@ -493,12 +507,12 @@ public:
/** Base class for all Descriptor implementations. */
class DescriptorImpl : public Descriptor
{
- //! Public key arguments for this descriptor (size 1 for PK, PKH, WPKH; any size for Multisig).
+protected:
+ //! Public key arguments for this descriptor (size 1 for PK, PKH, WPKH; any size for WSH and Multisig).
const std::vector<std::unique_ptr<PubkeyProvider>> m_pubkey_args;
//! The string name of the descriptor function.
const std::string m_name;
-protected:
//! The sub-descriptor arguments (empty for everything but SH and WSH).
//! In doc/descriptors.m this is referred to as SCRIPT expressions sh(SCRIPT)
//! and wsh(SCRIPT), and distinct from KEY expressions and ADDR expressions.
@@ -558,12 +572,12 @@ public:
if (pos++) ret += ",";
std::string tmp;
if (!scriptarg->ToStringHelper(arg, tmp, type, cache)) return false;
- ret += std::move(tmp);
+ ret += tmp;
}
return true;
}
- bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type, const DescriptorCache* cache = nullptr) const
+ virtual bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type, const DescriptorCache* cache = nullptr) const
{
std::string extra = ToStringExtra();
size_t pos = extra.size() > 0 ? 1 : 0;
@@ -582,7 +596,7 @@ public:
tmp = pubkey->ToString();
break;
}
- ret += std::move(tmp);
+ ret += tmp;
}
std::string subscript;
if (!ToStringSubScriptHelper(arg, subscript, type, cache)) return false;
@@ -598,7 +612,7 @@ public:
return AddChecksum(ret);
}
- bool ToPrivateString(const SigningProvider& arg, std::string& out) const final
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
{
bool ret = ToStringHelper(&arg, out, StringType::PRIVATE);
out = AddChecksum(out);
@@ -630,7 +644,7 @@ public:
assert(outscripts.size() == 1);
subscripts.emplace_back(std::move(outscripts[0]));
}
- out = Merge(std::move(out), std::move(subprovider));
+ out.Merge(std::move(subprovider));
std::vector<CPubKey> pubkeys;
pubkeys.reserve(entries.size());
@@ -684,6 +698,7 @@ public:
return OutputTypeFromDestination(m_destination);
}
bool IsSingleType() const final { return true; }
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const final { return false; }
};
/** A parsed raw(H) descriptor. */
@@ -704,6 +719,7 @@ public:
return OutputTypeFromDestination(dest);
}
bool IsSingleType() const final { return true; }
+ bool ToPrivateString(const SigningProvider& arg, std::string& out) const final { return false; }
};
/** A parsed pk(P) descriptor. */
@@ -882,7 +898,7 @@ protected:
if (!xpk.IsFullyValid()) return {};
builder.Finalize(xpk);
WitnessV1Taproot output = builder.GetOutput();
- out.tr_spenddata[output].Merge(builder.GetSpendData());
+ out.tr_trees[output] = builder;
out.pubkeys.emplace(keys[0].GetID(), keys[0]);
return Vector(GetScriptForDestination(output));
}
@@ -898,7 +914,7 @@ protected:
}
std::string tmp;
if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache)) return false;
- ret += std::move(tmp);
+ ret += tmp;
while (!path.empty() && path.back()) {
if (path.size() > 1) ret += '}';
path.pop_back();
@@ -917,6 +933,107 @@ public:
bool IsSingleType() const final { return true; }
};
+/* We instantiate Miniscript here with a simple integer as key type.
+ * The value of these key integers are an index in the
+ * DescriptorImpl::m_pubkey_args vector.
+ */
+
+/**
+ * The context for converting a Miniscript descriptor into a Script.
+ */
+class ScriptMaker {
+ //! Keys contained in the Miniscript (the evaluation of DescriptorImpl::m_pubkey_args).
+ const std::vector<CPubKey>& m_keys;
+
+public:
+ ScriptMaker(const std::vector<CPubKey>& keys LIFETIMEBOUND) : m_keys(keys) {}
+
+ std::vector<unsigned char> ToPKBytes(uint32_t key) const {
+ return {m_keys[key].begin(), m_keys[key].end()};
+ }
+
+ std::vector<unsigned char> ToPKHBytes(uint32_t key) const {
+ auto id = m_keys[key].GetID();
+ return {id.begin(), id.end()};
+ }
+};
+
+/**
+ * The context for converting a Miniscript descriptor to its textual form.
+ */
+class StringMaker {
+ //! To convert private keys for private descriptors.
+ const SigningProvider* m_arg;
+ //! Keys contained in the Miniscript (a reference to DescriptorImpl::m_pubkey_args).
+ const std::vector<std::unique_ptr<PubkeyProvider>>& m_pubkeys;
+ //! Whether to serialize keys as private or public.
+ bool m_private;
+
+public:
+ StringMaker(const SigningProvider* arg LIFETIMEBOUND, const std::vector<std::unique_ptr<PubkeyProvider>>& pubkeys LIFETIMEBOUND, bool priv)
+ : m_arg(arg), m_pubkeys(pubkeys), m_private(priv) {}
+
+ std::optional<std::string> ToString(uint32_t key) const
+ {
+ std::string ret;
+ if (m_private) {
+ if (!m_pubkeys[key]->ToPrivateString(*m_arg, ret)) return {};
+ } else {
+ ret = m_pubkeys[key]->ToString();
+ }
+ return ret;
+ }
+};
+
+class MiniscriptDescriptor final : public DescriptorImpl
+{
+private:
+ miniscript::NodeRef<uint32_t> m_node;
+
+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)));
+ }
+
+public:
+ MiniscriptDescriptor(std::vector<std::unique_ptr<PubkeyProvider>> providers, miniscript::NodeRef<uint32_t> node)
+ : DescriptorImpl(std::move(providers), "?"), m_node(std::move(node)) {}
+
+ bool ToStringHelper(const SigningProvider* arg, std::string& out, const StringType type,
+ const DescriptorCache* cache = nullptr) const override
+ {
+ if (const auto res = m_node->ToString(StringMaker(arg, m_pubkey_args, type == StringType::PRIVATE))) {
+ out = *res;
+ return true;
+ }
+ return false;
+ }
+
+ bool IsSolvable() const override { return false; } // For now, mark these descriptors as non-solvable (as we don't have signing logic for them).
+ bool IsSingleType() const final { return true; }
+};
+
+/** A parsed rawtr(...) descriptor. */
+class RawTRDescriptor final : public DescriptorImpl
+{
+protected:
+ std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, Span<const CScript> scripts, FlatSigningProvider& out) const override
+ {
+ assert(keys.size() == 1);
+ XOnlyPubKey xpk(keys[0]);
+ if (!xpk.IsFullyValid()) return {};
+ WitnessV1Taproot output{xpk};
+ return Vector(GetScriptForDestination(output));
+ }
+public:
+ RawTRDescriptor(std::unique_ptr<PubkeyProvider> output_key) : DescriptorImpl(Vector(std::move(output_key)), "rawtr") {}
+ std::optional<OutputType> GetOutputType() const override { return OutputType::BECH32M; }
+ bool IsSingleType() const final { return true; }
+};
+
////////////////////////////////////////////////////////////////////////////
// Parser //
////////////////////////////////////////////////////////////////////////////
@@ -1058,6 +1175,94 @@ 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));
}
+std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
+{
+ std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, false);
+ KeyOriginInfo info;
+ if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
+ return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
+ }
+ return key_provider;
+}
+
+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);
+ std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, true);
+ KeyOriginInfo info;
+ if (provider.GetKeyOriginByXOnly(xkey, info)) {
+ return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
+ }
+ return key_provider;
+}
+
+/**
+ * The context for parsing a Miniscript descriptor (either from Script or from its textual representation).
+ */
+struct KeyParser {
+ //! The Key type is an index in DescriptorImpl::m_pubkey_args
+ using Key = uint32_t;
+ //! Must not be nullptr if parsing from string.
+ FlatSigningProvider* m_out;
+ //! Must not be nullptr if parsing from Script.
+ const SigningProvider* m_in;
+ //! List of keys contained in the Miniscript.
+ 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;
+
+ KeyParser(FlatSigningProvider* out LIFETIMEBOUND, const SigningProvider* in LIFETIMEBOUND) : m_out(out), m_in(in) {}
+
+ bool KeyCompare(const Key& a, const Key& b) const {
+ return *m_keys.at(a) < *m_keys.at(b);
+ }
+
+ 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);
+ if (!pk) return {};
+ m_keys.push_back(std::move(pk));
+ return key;
+ }
+
+ std::optional<std::string> ToString(const Key& key) const
+ {
+ return m_keys.at(key)->ToString();
+ }
+
+ 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;
+ }
+ return {};
+ }
+
+ template<typename I> std::optional<Key> FromPKHBytes(I begin, I end) const
+ {
+ assert(end - begin == 20);
+ assert(m_in);
+ uint160 hash;
+ std::copy(begin, end, hash.begin());
+ 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;
+ }
+ return {};
+ }
+};
+
/** Parse a script in a particular context. */
std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
{
@@ -1267,6 +1472,20 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
error = "Can only have tr at top level";
return nullptr;
}
+ if (ctx == ParseScriptContext::TOP && Func("rawtr", expr)) {
+ auto arg = Expr(expr);
+ if (expr.size()) {
+ error = strprintf("rawtr(): only one key expected.");
+ return nullptr;
+ }
+ auto output_key = ParsePubkey(key_exp_index, arg, ParseScriptContext::P2TR, out, error);
+ if (!output_key) return nullptr;
+ ++key_exp_index;
+ return std::make_unique<RawTRDescriptor>(std::move(output_key));
+ } else if (Func("rawtr", expr)) {
+ error = "Can only have rawtr at top level";
+ return nullptr;
+ }
if (ctx == ParseScriptContext::TOP && Func("raw", expr)) {
std::string str(expr.begin(), expr.end());
if (!IsHex(str)) {
@@ -1279,6 +1498,45 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
error = "Can only have raw() at top level";
return nullptr;
}
+ // Process miniscript expressions.
+ {
+ KeyParser parser(&out, nullptr);
+ 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";
+ return nullptr;
+ }
+ if (parser.m_key_parsing_error != "") {
+ error = std::move(parser.m_key_parsing_error);
+ return nullptr;
+ }
+ if (!node->IsSane()) {
+ // Try to find the first insane sub for better error reporting.
+ auto insane_node = node.get();
+ if (const auto sub = node->FindInsaneSub()) insane_node = sub;
+ if (const auto str = insane_node->ToString(parser)) error = *str;
+ if (!insane_node->IsValid()) {
+ error += " is invalid";
+ } else {
+ error += " is not sane";
+ if (!insane_node->IsNonMalleable()) {
+ error += ": malleable witnesses exist";
+ } else if (insane_node == node.get() && !insane_node->NeedsSignature()) {
+ error += ": witnesses without signature exist";
+ } else if (!insane_node->CheckTimeLocksMix()) {
+ error += ": contains mixes of timelocks expressed in blocks and seconds";
+ } else if (!insane_node->CheckDuplicateKey()) {
+ error += ": contains duplicate public keys";
+ } else if (!insane_node->ValidSatisfactions()) {
+ error += ": needs witnesses that may exceed resource limits";
+ }
+ }
+ return nullptr;
+ }
+ return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(node));
+ }
+ }
if (ctx == ParseScriptContext::P2SH) {
error = "A function is needed within P2SH";
return nullptr;
@@ -1290,29 +1548,6 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
return nullptr;
}
-std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
-{
- std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, false);
- KeyOriginInfo info;
- if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
- return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
- }
- return key_provider;
-}
-
-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);
- std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, true);
- KeyOriginInfo info;
- if (provider.GetKeyOriginByXOnly(xkey, info)) {
- return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
- }
- return key_provider;
-}
-
std::unique_ptr<DescriptorImpl> InferMultiA(const CScript& script, ParseScriptContext ctx, const SigningProvider& provider)
{
auto match = MatchMultiA(script);
@@ -1424,6 +1659,21 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo
}
}
}
+ // If the above doesn't work, construct a rawtr() descriptor with just the encoded x-only pubkey.
+ if (pubkey.IsFullyValid()) {
+ auto key = InferXOnlyPubkey(pubkey, ParseScriptContext::P2TR, provider);
+ if (key) {
+ return std::make_unique<RawTRDescriptor>(std::move(key));
+ }
+ }
+ }
+
+ if (ctx == ParseScriptContext::P2WSH) {
+ KeyParser parser(nullptr, &provider);
+ auto node = miniscript::FromScript(script, parser);
+ if (node && node->IsSane()) {
+ return std::make_unique<MiniscriptDescriptor>(std::move(parser.m_keys), std::move(node));
+ }
}
CTxDestination dest;
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 9f56301377..38bb11aad4 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1342,7 +1342,7 @@ public:
template <class T>
uint256 GetPrevoutsSHA256(const T& txTo)
{
- CHashWriter ss(SER_GETHASH, 0);
+ HashWriter ss{};
for (const auto& txin : txTo.vin) {
ss << txin.prevout;
}
@@ -1353,7 +1353,7 @@ uint256 GetPrevoutsSHA256(const T& txTo)
template <class T>
uint256 GetSequencesSHA256(const T& txTo)
{
- CHashWriter ss(SER_GETHASH, 0);
+ HashWriter ss{};
for (const auto& txin : txTo.vin) {
ss << txin.nSequence;
}
@@ -1364,7 +1364,7 @@ uint256 GetSequencesSHA256(const T& txTo)
template <class T>
uint256 GetOutputsSHA256(const T& txTo)
{
- CHashWriter ss(SER_GETHASH, 0);
+ HashWriter ss{};
for (const auto& txout : txTo.vout) {
ss << txout;
}
@@ -1374,7 +1374,7 @@ uint256 GetOutputsSHA256(const T& txTo)
/** Compute the (single) SHA256 of the concatenation of all amounts spent by a tx. */
uint256 GetSpentAmountsSHA256(const std::vector<CTxOut>& outputs_spent)
{
- CHashWriter ss(SER_GETHASH, 0);
+ HashWriter ss{};
for (const auto& txout : outputs_spent) {
ss << txout.nValue;
}
@@ -1384,7 +1384,7 @@ uint256 GetSpentAmountsSHA256(const std::vector<CTxOut>& outputs_spent)
/** Compute the (single) SHA256 of the concatenation of all scriptPubKeys spent by a tx. */
uint256 GetSpentScriptsSHA256(const std::vector<CTxOut>& outputs_spent)
{
- CHashWriter ss(SER_GETHASH, 0);
+ HashWriter ss{};
for (const auto& txout : outputs_spent) {
ss << txout.scriptPubKey;
}
@@ -1458,9 +1458,9 @@ template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo,
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
-const CHashWriter HASHER_TAPSIGHASH = TaggedHash("TapSighash");
-const CHashWriter HASHER_TAPLEAF = TaggedHash("TapLeaf");
-const CHashWriter HASHER_TAPBRANCH = TaggedHash("TapBranch");
+const HashWriter HASHER_TAPSIGHASH{TaggedHash("TapSighash")};
+const HashWriter HASHER_TAPLEAF{TaggedHash("TapLeaf")};
+const HashWriter HASHER_TAPBRANCH{TaggedHash("TapBranch")};
static bool HandleMissingData(MissingDataBehavior mdb)
{
@@ -1499,7 +1499,7 @@ bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, cons
return HandleMissingData(mdb);
}
- CHashWriter ss = HASHER_TAPSIGHASH;
+ HashWriter ss{HASHER_TAPSIGHASH};
// Epoch
static constexpr uint8_t EPOCH = 0;
@@ -1544,7 +1544,7 @@ bool SignatureHashSchnorr(uint256& hash_out, ScriptExecutionData& execdata, cons
if (output_type == SIGHASH_SINGLE) {
if (in_pos >= tx_to.vout.size()) return false;
if (!execdata.m_output_hash) {
- CHashWriter sha_single_output(SER_GETHASH, 0);
+ HashWriter sha_single_output{};
sha_single_output << tx_to.vout[in_pos];
execdata.m_output_hash = sha_single_output.GetSHA256();
}
@@ -1587,12 +1587,12 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
hashOutputs = cacheready ? cache->hashOutputs : SHA256Uint256(GetOutputsSHA256(txTo));
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
- CHashWriter ss(SER_GETHASH, 0);
+ HashWriter ss{};
ss << txTo.vout[nIn];
hashOutputs = ss.GetHash();
}
- CHashWriter ss(SER_GETHASH, 0);
+ HashWriter ss{};
// Version
ss << txTo.nVersion;
// Input prevouts/nSequence (none/all, depending on flags)
@@ -1627,7 +1627,7 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn
CTransactionSignatureSerializer<T> txTmp(txTo, scriptCode, nIn, nHashType);
// Serialize and hash
- CHashWriter ss(SER_GETHASH, 0);
+ HashWriter ss{};
ss << txTmp << nHashType;
return ss.GetHash();
}
@@ -1827,7 +1827,7 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
uint256 ComputeTapleafHash(uint8_t leaf_version, const CScript& script)
{
- return (CHashWriter(HASHER_TAPLEAF) << leaf_version << script).GetSHA256();
+ return (HashWriter{HASHER_TAPLEAF} << leaf_version << script).GetSHA256();
}
uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint256& tapleaf_hash)
@@ -1839,7 +1839,7 @@ uint256 ComputeTaprootMerkleRoot(Span<const unsigned char> control, const uint25
const int path_len = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
uint256 k = tapleaf_hash;
for (int i = 0; i < path_len; ++i) {
- CHashWriter ss_branch{HASHER_TAPBRANCH};
+ HashWriter ss_branch{HASHER_TAPBRANCH};
Span node{Span{control}.subspan(TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * i, TAPROOT_CONTROL_NODE_SIZE)};
if (std::lexicographical_compare(k.begin(), k.end(), node.begin(), node.end())) {
ss_branch << k << node;
@@ -1902,7 +1902,7 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
if (stack.size() >= 2 && !stack.back().empty() && stack.back()[0] == ANNEX_TAG) {
// Drop annex (this is non-standard; see IsWitnessStandard)
const valtype& annex = SpanPopBack(stack);
- execdata.m_annex_hash = (CHashWriter(SER_GETHASH, 0) << annex).GetSHA256();
+ execdata.m_annex_hash = (HashWriter{} << annex).GetSHA256();
execdata.m_annex_present = true;
} else {
execdata.m_annex_present = false;
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index adf454aa15..ba910cc945 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -233,9 +233,9 @@ static constexpr size_t TAPROOT_CONTROL_NODE_SIZE = 32;
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT = 128;
static constexpr size_t TAPROOT_CONTROL_MAX_SIZE = TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT;
-extern const CHashWriter HASHER_TAPSIGHASH; //!< Hasher with tag "TapSighash" pre-fed to it.
-extern const CHashWriter HASHER_TAPLEAF; //!< Hasher with tag "TapLeaf" pre-fed to it.
-extern const CHashWriter HASHER_TAPBRANCH; //!< Hasher with tag "TapBranch" pre-fed to it.
+extern const HashWriter HASHER_TAPSIGHASH; //!< Hasher with tag "TapSighash" pre-fed to it.
+extern const HashWriter HASHER_TAPLEAF; //!< Hasher with tag "TapLeaf" pre-fed to it.
+extern const HashWriter HASHER_TAPBRANCH; //!< Hasher with tag "TapBranch" pre-fed to it.
template <class T>
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr);
@@ -307,10 +307,10 @@ using MutableTransactionSignatureChecker = GenericTransactionSignatureChecker<CM
class DeferringSignatureChecker : public BaseSignatureChecker
{
protected:
- BaseSignatureChecker& m_checker;
+ const BaseSignatureChecker& m_checker;
public:
- DeferringSignatureChecker(BaseSignatureChecker& checker) : m_checker(checker) {}
+ DeferringSignatureChecker(const BaseSignatureChecker& checker) : m_checker(checker) {}
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override
{
diff --git a/src/script/miniscript.h b/src/script/miniscript.h
index 2c239c2678..c4f41e0adf 100644
--- a/src/script/miniscript.h
+++ b/src/script/miniscript.h
@@ -276,6 +276,8 @@ struct StackSize {
StackSize(MaxInt<uint32_t> in_sat, MaxInt<uint32_t> in_dsat) : sat(in_sat), dsat(in_dsat) {};
};
+struct NoDupCheck {};
+
} // namespace internal
//! A node in a miniscript expression.
@@ -301,8 +303,13 @@ private:
const Type typ;
//! Cached script length (computed by CalcScriptLen).
const size_t scriptlen;
- //! Whether a public key appears more than once in this node.
- const bool duplicate_key;
+ //! Whether a public key appears more than once in this node. This value is initialized
+ //! by all constructors except the NoDupCheck ones. The NoDupCheck ones skip the
+ //! computation, requiring it to be done manually by invoking DuplicateKeyCheck().
+ //! DuplicateKeyCheck(), or a non-NoDupCheck constructor, will compute has_duplicate_keys
+ //! for all subnodes as well.
+ mutable std::optional<bool> has_duplicate_keys;
+
//! Compute the length of the script for this miniscript (including children).
size_t CalcScriptLen() const {
@@ -429,6 +436,21 @@ private:
));
}
+ /** Like TreeEval, but without downfn or State type.
+ * upfn takes (const Node&, Span<Result>) and returns Result. */
+ template<typename Result, typename UpFn>
+ Result TreeEval(UpFn upfn) const
+ {
+ struct DummyState {};
+ return std::move(*TreeEvalMaybe<Result>(DummyState{},
+ [](DummyState, const Node&, size_t) { return DummyState{}; },
+ [&upfn](DummyState, const Node& node, Span<Result> subs) {
+ Result res{upfn(node, subs)};
+ return std::optional<Result>(std::move(res));
+ }
+ ));
+ }
+
/** Compare two miniscript subtrees, using a non-recursive algorithm. */
friend int Compare(const Node<Key>& node1, const Node<Key>& node2)
{
@@ -639,6 +661,7 @@ public:
return TreeEvalMaybe<std::string>(false, downfn, upfn);
}
+private:
internal::Ops CalcOps() const {
switch (fragment) {
case Fragment::JUST_1: return {0, 0, {}};
@@ -762,11 +785,14 @@ public:
assert(false);
}
- /** Check whether any key is repeated.
+public:
+ /** Update duplicate key information in this Node.
+ *
* This uses a custom key comparator provided by the context in order to still detect duplicates
* for more complicated types.
*/
- template<typename Ctx> bool ContainsDuplicateKey(const Ctx& ctx) const {
+ template<typename Ctx> void DuplicateKeyCheck(const Ctx& ctx) const
+ {
// We cannot use a lambda here, as lambdas are non assignable, and the set operations
// below require moving the comparators around.
struct Comp {
@@ -774,31 +800,55 @@ public:
Comp(const Ctx& ctx) : ctx_ptr(&ctx) {}
bool operator()(const Key& a, const Key& b) const { return ctx_ptr->KeyCompare(a, b); }
};
- using set = std::set<Key, Comp>;
- auto upfn = [this, &ctx](const Node& node, Span<set> subs) -> std::optional<set> {
- if (&node != this && node.duplicate_key) return {};
+ // state in the recursive computation:
+ // - std::nullopt means "this node has duplicates"
+ // - an std::set means "this node has no duplicate keys, and they are: ...".
+ using keyset = std::set<Key, Comp>;
+ using state = std::optional<keyset>;
+
+ auto upfn = [&ctx](const Node& node, Span<state> subs) -> state {
+ // If this node is already known to have duplicates, nothing left to do.
+ if (node.has_duplicate_keys.has_value() && *node.has_duplicate_keys) return {};
+ // Check if one of the children is already known to have duplicates.
+ for (auto& sub : subs) {
+ if (!sub.has_value()) {
+ node.has_duplicate_keys = true;
+ return {};
+ }
+ }
+
+ // Start building the set of keys involved in this node and children.
+ // Start by keys in this node directly.
size_t keys_count = node.keys.size();
- set key_set{node.keys.begin(), node.keys.end(), Comp(ctx)};
- if (key_set.size() != keys_count) return {};
+ keyset key_set{node.keys.begin(), node.keys.end(), Comp(ctx)};
+ if (key_set.size() != keys_count) {
+ // It already has duplicates; bail out.
+ node.has_duplicate_keys = true;
+ return {};
+ }
- for (auto& sub: subs) {
- keys_count += sub.size();
+ // Merge the keys from the children into this set.
+ for (auto& sub : subs) {
+ keys_count += sub->size();
// Small optimization: std::set::merge is linear in the size of the second arg but
// logarithmic in the size of the first.
- if (key_set.size() < sub.size()) std::swap(key_set, sub);
- key_set.merge(sub);
- if (key_set.size() != keys_count) return {};
+ if (key_set.size() < sub->size()) std::swap(key_set, *sub);
+ key_set.merge(*sub);
+ if (key_set.size() != keys_count) {
+ node.has_duplicate_keys = true;
+ return {};
+ }
}
+ node.has_duplicate_keys = false;
return key_set;
};
- return !TreeEvalMaybe<set>(upfn);
+ TreeEval<state>(upfn);
}
-public:
//! Return the size of the script for this expression (faster than ToScript().size()).
size_t ScriptSize() const { return scriptlen; }
@@ -818,6 +868,15 @@ public:
//! Return the expression type.
Type GetType() const { return typ; }
+ //! 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* {
+ for (auto& sub: subs) if (sub) return sub;
+ if (!node.IsSaneSubexpression()) return &node;
+ return nullptr;
+ });
+ }
+
//! Check whether this node is valid at all.
bool IsValid() const { return !(GetType() == ""_mst) && ScriptSize() <= MAX_STANDARD_P2WSH_SCRIPT_SIZE; }
@@ -834,7 +893,7 @@ public:
bool CheckTimeLocksMix() const { return GetType() << "k"_mst; }
//! Check whether there is no duplicate key across this fragment and all its sub-fragments.
- bool CheckDuplicateKey() const { return !duplicate_key; }
+ bool CheckDuplicateKey() const { return has_duplicate_keys && !*has_duplicate_keys; }
//! Whether successful non-malleable satisfactions are guaranteed to be valid.
bool ValidSatisfactions() const { return IsValid() && CheckOpsLimit() && CheckStackSize(); }
@@ -848,13 +907,21 @@ public:
//! Equality testing.
bool operator==(const Node<Key>& arg) const { return Compare(*this, arg) == 0; }
- // Constructors with various argument combinations.
- template <typename Ctx> Node(const Ctx& 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)), ops(CalcOps()), ss(CalcStackSize()), typ(CalcType()), scriptlen(CalcScriptLen()), duplicate_key(ContainsDuplicateKey(ctx)) {}
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<unsigned char> arg, uint32_t val = 0) : fragment(nt), k(val), data(std::move(arg)), ops(CalcOps()), ss(CalcStackSize()), typ(CalcType()), scriptlen(CalcScriptLen()), duplicate_key(ContainsDuplicateKey(ctx)) {}
- template <typename Ctx> Node(const Ctx& ctx, 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()), typ(CalcType()), scriptlen(CalcScriptLen()), duplicate_key(ContainsDuplicateKey(ctx)) {}
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<Key> key, uint32_t val = 0) : fragment(nt), k(val), keys(std::move(key)), ops(CalcOps()), ss(CalcStackSize()), typ(CalcType()), scriptlen(CalcScriptLen()), duplicate_key(ContainsDuplicateKey(ctx)) {}
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>> sub, uint32_t val = 0) : fragment(nt), k(val), subs(std::move(sub)), ops(CalcOps()), ss(CalcStackSize()), typ(CalcType()), scriptlen(CalcScriptLen()), duplicate_key(ContainsDuplicateKey(ctx)) {}
- template <typename Ctx> Node(const Ctx& ctx, Fragment nt, uint32_t val = 0) : fragment(nt), k(val), ops(CalcOps()), ss(CalcStackSize()), typ(CalcType()), scriptlen(CalcScriptLen()), duplicate_key(ContainsDuplicateKey(ctx)) {}
+ // 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()), 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()), 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()), 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()), 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()), typ(CalcType()), scriptlen(CalcScriptLen()) {}
+ Node(internal::NoDupCheck, Fragment nt, uint32_t val = 0) : fragment(nt), k(val), ops(CalcOps()), ss(CalcStackSize()), 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); }
};
namespace internal {
@@ -941,24 +1008,40 @@ 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, typename Ctx>
-void BuildBack(const Ctx& ctx, Fragment nt, std::vector<NodeRef<Key>>& constructed, const bool reverse = false)
+template<typename Key>
+void BuildBack(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>(ctx, nt, Vector(std::move(child), std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, nt, Vector(std::move(child), std::move(constructed.back())));
} else {
- constructed.back() = MakeNodeRef<Key>(ctx, nt, Vector(std::move(constructed.back()), std::move(child)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, nt, Vector(std::move(constructed.back()), std::move(child)));
}
}
-//! Parse a miniscript from its textual descriptor form.
+/**
+ * Parse a miniscript from its textual descriptor form.
+ * This does not check whether the script is valid, let alone sane. The caller is expected to use
+ * the `IsValidTopLevel()` and `IsSaneTopLevel()` to check for these properties on the node.
+ */
template<typename Key, typename Ctx>
inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
{
using namespace spanparsing;
+ // Account for the minimum script size for all parsed fragments so far. It "borrows" 1
+ // script byte from all leaf nodes, counting it instead whenever a space for a recursive
+ // expression is added (through andor, and_*, or_*, thresh). This guarantees that all fragments
+ // increment the script_size by at least one, except for:
+ // - "0", "1": these leafs are only a single byte, so their subtracted-from increment is 0.
+ // This is not an issue however, as "space" for them has to be created by combinators,
+ // which do increment script_size.
+ // - "v:": the v wrapper adds nothing as in some cases it results in no opcode being added
+ // (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};
+
// The two integers are used to hold state for thresh()
std::vector<std::tuple<ParseContext, int64_t, int64_t>> to_parse;
std::vector<NodeRef<Key>> constructed;
@@ -966,14 +1049,16 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
while (!to_parse.empty()) {
+ if (script_size > MAX_STANDARD_P2WSH_SCRIPT_SIZE) return {};
+
// Get the current context we are decoding within
auto [cur_context, n, k] = to_parse.back();
to_parse.pop_back();
switch (cur_context) {
case ParseContext::WRAPPED_EXPR: {
- int colon_index = -1;
- for (int i = 1; i < (int)in.size(); ++i) {
+ std::optional<size_t> colon_index{};
+ for (size_t i = 1; i < in.size(); ++i) {
if (in[i] == ':') {
colon_index = i;
break;
@@ -981,106 +1066,131 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
if (in[i] < 'a' || in[i] > 'z') break;
}
// If there is no colon, this loop won't execute
- for (int j = 0; j < colon_index; ++j) {
+ 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 (in[j] == 'a') {
+ script_size += 2;
to_parse.emplace_back(ParseContext::ALT, -1, -1);
} else if (in[j] == 's') {
+ script_size += 1;
to_parse.emplace_back(ParseContext::SWAP, -1, -1);
} else if (in[j] == 'c') {
+ script_size += 1;
to_parse.emplace_back(ParseContext::CHECK, -1, -1);
} else if (in[j] == 'd') {
+ script_size += 3;
to_parse.emplace_back(ParseContext::DUP_IF, -1, -1);
} else if (in[j] == 'j') {
+ script_size += 4;
to_parse.emplace_back(ParseContext::NON_ZERO, -1, -1);
} else if (in[j] == 'n') {
+ script_size += 1;
to_parse.emplace_back(ParseContext::ZERO_NOTEQUAL, -1, -1);
} else if (in[j] == 'v') {
+ // do not permit "...vv...:"; it's not valid, and also doesn't trigger early
+ // failure as script_size isn't incremented.
+ if (last_was_v) return {};
to_parse.emplace_back(ParseContext::VERIFY, -1, -1);
} else if (in[j] == 'u') {
+ script_size += 4;
to_parse.emplace_back(ParseContext::WRAP_U, -1, -1);
} else if (in[j] == 't') {
+ script_size += 1;
to_parse.emplace_back(ParseContext::WRAP_T, -1, -1);
} else if (in[j] == 'l') {
// The l: wrapper is equivalent to or_i(0,X)
- constructed.push_back(MakeNodeRef<Key>(ctx, Fragment::JUST_0));
+ script_size += 4;
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_0));
to_parse.emplace_back(ParseContext::OR_I, -1, -1);
} else {
return {};
}
+ last_was_v = (in[j] == 'v');
}
to_parse.emplace_back(ParseContext::EXPR, -1, -1);
- in = in.subspan(colon_index + 1);
+ if (colon_index) in = in.subspan(*colon_index + 1);
break;
}
case ParseContext::EXPR: {
if (Const("0", in)) {
- constructed.push_back(MakeNodeRef<Key>(ctx, Fragment::JUST_0));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_0));
} else if (Const("1", in)) {
- constructed.push_back(MakeNodeRef<Key>(ctx, Fragment::JUST_1));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::WRAP_C, Vector(MakeNodeRef<Key>(ctx, Fragment::PK_K, Vector(std::move(key))))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_C, Vector(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_K, Vector(std::move(key))))));
in = in.subspan(key_size + 1);
+ script_size += 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>(ctx, Fragment::WRAP_C, Vector(MakeNodeRef<Key>(ctx, Fragment::PK_H, Vector(std::move(key))))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_C, Vector(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::PK_K, Vector(std::move(key))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_K, Vector(std::move(key))));
in = in.subspan(key_size + 1);
+ script_size += 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>(ctx, Fragment::PK_H, Vector(std::move(key))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::SHA256, std::move(hash)));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::RIPEMD160, std::move(hash)));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::HASH256, std::move(hash)));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::HASH160, std::move(hash)));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::HASH160, std::move(hash)));
in = in.subspan(hash_size + 1);
+ script_size += 26;
} else if (Const("after(", in)) {
int arg_size = FindNextChar(in, ')');
if (arg_size < 1) return {};
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>(ctx, Fragment::AFTER, num));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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)) {
int arg_size = FindNextChar(in, ')');
if (arg_size < 1) return {};
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>(ctx, Fragment::OLDER, num));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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, ',');
@@ -1100,7 +1210,8 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
}
if (keys.size() < 1 || keys.size() > 20) return {};
if (k < 1 || k > (int64_t)keys.size()) return {};
- constructed.push_back(MakeNodeRef<Key>(ctx, Fragment::MULTI, std::move(keys), k));
+ script_size += 2 + (keys.size() > 16) + (k > 16) + 34 * keys.size();
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::MULTI, std::move(keys), k));
} else if (Const("thresh(", in)) {
int next_comma = FindNextChar(in, ',');
if (next_comma < 1) return {};
@@ -1110,6 +1221,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
// n = 1 here because we read the first WRAPPED_EXPR before reaching THRESH
to_parse.emplace_back(ParseContext::THRESH, 1, k);
to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
+ script_size += 2 + (k > 16) + (k > 0x7f) + (k > 0x7fff) + (k > 0x7fffff);
} else if (Const("andor(", in)) {
to_parse.emplace_back(ParseContext::ANDOR, -1, -1);
to_parse.emplace_back(ParseContext::CLOSE_BRACKET, -1, -1);
@@ -1118,21 +1230,29 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
to_parse.emplace_back(ParseContext::COMMA, -1, -1);
to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
+ script_size += 5;
} else {
if (Const("and_n(", in)) {
to_parse.emplace_back(ParseContext::AND_N, -1, -1);
+ script_size += 5;
} else if (Const("and_b(", in)) {
to_parse.emplace_back(ParseContext::AND_B, -1, -1);
+ script_size += 2;
} else if (Const("and_v(", in)) {
to_parse.emplace_back(ParseContext::AND_V, -1, -1);
+ script_size += 1;
} else if (Const("or_b(", in)) {
to_parse.emplace_back(ParseContext::OR_B, -1, -1);
+ script_size += 2;
} else if (Const("or_c(", in)) {
to_parse.emplace_back(ParseContext::OR_C, -1, -1);
+ script_size += 3;
} else if (Const("or_d(", in)) {
to_parse.emplace_back(ParseContext::OR_D, -1, -1);
+ script_size += 4;
} else if (Const("or_i(", in)) {
to_parse.emplace_back(ParseContext::OR_I, -1, -1);
+ script_size += 4;
} else {
return {};
}
@@ -1144,69 +1264,70 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
break;
}
case ParseContext::ALT: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_A, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_A, Vector(std::move(constructed.back())));
break;
}
case ParseContext::SWAP: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_S, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_S, Vector(std::move(constructed.back())));
break;
}
case ParseContext::CHECK: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_C, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_C, Vector(std::move(constructed.back())));
break;
}
case ParseContext::DUP_IF: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_D, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_D, Vector(std::move(constructed.back())));
break;
}
case ParseContext::NON_ZERO: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_J, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_J, Vector(std::move(constructed.back())));
break;
}
case ParseContext::ZERO_NOTEQUAL: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_N, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_N, Vector(std::move(constructed.back())));
break;
}
case ParseContext::VERIFY: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_V, Vector(std::move(constructed.back())));
+ script_size += (constructed.back()->GetType() << "x"_mst);
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_V, Vector(std::move(constructed.back())));
break;
}
case ParseContext::WRAP_U: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::OR_I, Vector(std::move(constructed.back()), MakeNodeRef<Key>(ctx, Fragment::JUST_0)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::OR_I, Vector(std::move(constructed.back()), MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_0)));
break;
}
case ParseContext::WRAP_T: {
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::AND_V, Vector(std::move(constructed.back()), MakeNodeRef<Key>(ctx, Fragment::JUST_1)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::AND_V, Vector(std::move(constructed.back()), MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_1)));
break;
}
case ParseContext::AND_B: {
- BuildBack(ctx, Fragment::AND_B, constructed);
+ BuildBack(Fragment::AND_B, constructed);
break;
}
case ParseContext::AND_N: {
auto mid = std::move(constructed.back());
constructed.pop_back();
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), MakeNodeRef<Key>(ctx, Fragment::JUST_0)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), MakeNodeRef<Key>(ctx, Fragment::JUST_0)));
break;
}
case ParseContext::AND_V: {
- BuildBack(ctx, Fragment::AND_V, constructed);
+ BuildBack(Fragment::AND_V, constructed);
break;
}
case ParseContext::OR_B: {
- BuildBack(ctx, Fragment::OR_B, constructed);
+ BuildBack(Fragment::OR_B, constructed);
break;
}
case ParseContext::OR_C: {
- BuildBack(ctx, Fragment::OR_C, constructed);
+ BuildBack(Fragment::OR_C, constructed);
break;
}
case ParseContext::OR_D: {
- BuildBack(ctx, Fragment::OR_D, constructed);
+ BuildBack(Fragment::OR_D, constructed);
break;
}
case ParseContext::OR_I: {
- BuildBack(ctx, Fragment::OR_I, constructed);
+ BuildBack(Fragment::OR_I, constructed);
break;
}
case ParseContext::ANDOR: {
@@ -1214,7 +1335,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>(ctx, Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), std::move(right)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::ANDOR, Vector(std::move(constructed.back()), std::move(mid), std::move(right)));
break;
}
case ParseContext::THRESH: {
@@ -1223,6 +1344,7 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
in = in.subspan(1);
to_parse.emplace_back(ParseContext::THRESH, n+1, k);
to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
+ script_size += 2;
} else if (in[0] == ')') {
if (k > n) return {};
in = in.subspan(1);
@@ -1233,7 +1355,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>(ctx, Fragment::THRESH, std::move(subs), k));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::THRESH, std::move(subs), k));
} else {
return {};
}
@@ -1254,9 +1376,10 @@ inline NodeRef<Key> Parse(Span<const char> in, const Ctx& ctx)
// Sanity checks on the produced miniscript
assert(constructed.size() == 1);
+ assert(constructed[0]->ScriptSize() == script_size);
if (in.size() > 0) return {};
const NodeRef<Key> tl_node = std::move(constructed.front());
- if (!tl_node->IsValidTopLevel()) return {};
+ tl_node->DuplicateKeyCheck(ctx);
return tl_node;
}
@@ -1368,12 +1491,12 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
// Constants
if (in[0].first == OP_1) {
++in;
- constructed.push_back(MakeNodeRef<Key>(ctx, Fragment::JUST_1));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_1));
break;
}
if (in[0].first == OP_0) {
++in;
- constructed.push_back(MakeNodeRef<Key>(ctx, Fragment::JUST_0));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::JUST_0));
break;
}
// Public keys
@@ -1381,14 +1504,14 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
auto key = ctx.FromPKBytes(in[0].second.begin(), in[0].second.end());
if (!key) return {};
++in;
- constructed.push_back(MakeNodeRef<Key>(ctx, Fragment::PK_K, Vector(std::move(*key))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::PK_H, Vector(std::move(*key))));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::PK_H, Vector(std::move(*key))));
break;
}
// Time locks
@@ -1396,31 +1519,31 @@ 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>(ctx, Fragment::OLDER, *num));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::AFTER, *num));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::SHA256, in[1].second));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::RIPEMD160, in[1].second));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::HASH256, in[1].second));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::HASH160, in[1].second));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::HASH160, in[1].second));
in += 7;
break;
}
@@ -1441,7 +1564,7 @@ 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>(ctx, Fragment::MULTI, std::move(keys), *k));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::MULTI, std::move(keys), *k));
break;
}
/** In the following wrappers, we only need to push SINGLE_BKV_EXPR rather
@@ -1536,63 +1659,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>(ctx, Fragment::WRAP_S, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, 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>(ctx, Fragment::WRAP_A, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_A, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::CHECK: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_C, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_C, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::DUP_IF: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_D, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_D, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::VERIFY: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_V, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_V, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::NON_ZERO: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_J, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_J, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::ZERO_NOTEQUAL: {
if (constructed.empty()) return {};
- constructed.back() = MakeNodeRef<Key>(ctx, Fragment::WRAP_N, Vector(std::move(constructed.back())));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::WRAP_N, Vector(std::move(constructed.back())));
break;
}
case DecodeContext::AND_V: {
if (constructed.size() < 2) return {};
- BuildBack(ctx, Fragment::AND_V, constructed, /*reverse=*/true);
+ BuildBack(Fragment::AND_V, constructed, /*reverse=*/true);
break;
}
case DecodeContext::AND_B: {
if (constructed.size() < 2) return {};
- BuildBack(ctx, Fragment::AND_B, constructed, /*reverse=*/true);
+ BuildBack(Fragment::AND_B, constructed, /*reverse=*/true);
break;
}
case DecodeContext::OR_B: {
if (constructed.size() < 2) return {};
- BuildBack(ctx, Fragment::OR_B, constructed, /*reverse=*/true);
+ BuildBack(Fragment::OR_B, constructed, /*reverse=*/true);
break;
}
case DecodeContext::OR_C: {
if (constructed.size() < 2) return {};
- BuildBack(ctx, Fragment::OR_C, constructed, /*reverse=*/true);
+ BuildBack(Fragment::OR_C, constructed, /*reverse=*/true);
break;
}
case DecodeContext::OR_D: {
if (constructed.size() < 2) return {};
- BuildBack(ctx, Fragment::OR_D, constructed, /*reverse=*/true);
+ BuildBack(Fragment::OR_D, constructed, /*reverse=*/true);
break;
}
case DecodeContext::ANDOR: {
@@ -1602,7 +1725,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>(ctx, Fragment::ANDOR, Vector(std::move(left), std::move(mid), std::move(right)));
+ constructed.back() = MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::ANDOR, Vector(std::move(left), std::move(mid), std::move(right)));
break;
}
case DecodeContext::THRESH_W: {
@@ -1626,7 +1749,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>(ctx, Fragment::THRESH, std::move(subs), k));
+ constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, Fragment::THRESH, std::move(subs), k));
break;
}
case DecodeContext::ENDIF: {
@@ -1676,7 +1799,7 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
if (in >= last) return {};
if (in[0].first == OP_IF) {
++in;
- BuildBack(ctx, Fragment::OR_I, constructed, /*reverse=*/true);
+ BuildBack(Fragment::OR_I, constructed, /*reverse=*/true);
} else if (in[0].first == OP_NOTIF) {
++in;
to_parse.emplace_back(DecodeContext::ANDOR, -1, -1);
@@ -1691,6 +1814,7 @@ inline NodeRef<Key> DecodeScript(I& in, I last, const Ctx& ctx)
}
if (constructed.size() != 1) return {};
const NodeRef<Key> tl_node = std::move(constructed.front());
+ tl_node->DuplicateKeyCheck(ctx);
// Note that due to how ComputeType works (only assign the type to the node if the
// subs' types are valid) this would fail if any node of tree is badly typed.
if (!tl_node->IsValidTopLevel()) return {};
@@ -1707,6 +1831,8 @@ inline NodeRef<typename Ctx::Key> FromString(const std::string& str, const Ctx&
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 {};
auto decomposed = DecomposeScript(script);
if (!decomposed) return {};
auto it = decomposed->begin();
diff --git a/src/script/script.h b/src/script/script.h
index 3b799ad637..1e5f694d52 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -588,7 +588,6 @@ CScript BuildScript(Ts&&... inputs)
int cnt{0};
([&ret, &cnt] (Ts&& input) {
- cnt++;
if constexpr (std::is_same_v<std::remove_cv_t<std::remove_reference_t<Ts>>, CScript>) {
// If it is a CScript, extend ret with it. Move or copy the first element instead.
if (cnt == 0) {
@@ -600,6 +599,7 @@ CScript BuildScript(Ts&&... inputs)
// Otherwise invoke CScript::operator<<.
ret << input;
}
+ cnt++;
} (std::forward<Ts>(inputs)), ...);
return ret;
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index 4e2acc463a..e507ec7528 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -14,6 +14,7 @@
#include <algorithm>
#include <mutex>
+#include <optional>
#include <shared_mutex>
#include <vector>
@@ -75,7 +76,7 @@ public:
std::unique_lock<std::shared_mutex> lock(cs_sigcache);
setValid.insert(entry);
}
- uint32_t setup_bytes(size_t n)
+ std::optional<std::pair<uint32_t, size_t>> setup_bytes(size_t n)
{
return setValid.setup_bytes(n);
}
@@ -92,14 +93,15 @@ static CSignatureCache signatureCache;
// To be called once in AppInitMain/BasicTestingSetup to initialize the
// signatureCache.
-void InitSignatureCache()
+bool InitSignatureCache(size_t max_size_bytes)
{
- // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
- // setup_bytes creates the minimum possible cache (2 elements).
- size_t nMaxCacheSize = std::min(std::max((int64_t)0, gArgs.GetIntArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE) / 2), MAX_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20);
- size_t nElems = signatureCache.setup_bytes(nMaxCacheSize);
- LogPrintf("Using %zu MiB out of %zu/2 requested for signature cache, able to store %zu elements\n",
- (nElems*sizeof(uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
+ auto setup_results = signatureCache.setup_bytes(max_size_bytes);
+ if (!setup_results) return false;
+
+ const auto [num_elems, approx_size_bytes] = *setup_results;
+ LogPrintf("Using %zu MiB out of %zu MiB requested for signature cache, able to store %zu elements\n",
+ approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
+ return true;
}
bool CachingTransactionSignatureChecker::VerifyECDSASignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
diff --git a/src/script/sigcache.h b/src/script/sigcache.h
index 1e21d6f340..290955090d 100644
--- a/src/script/sigcache.h
+++ b/src/script/sigcache.h
@@ -10,14 +10,13 @@
#include <span.h>
#include <util/hasher.h>
+#include <optional>
#include <vector>
-// DoS prevention: limit cache size to 32MB (over 1000000 entries on 64-bit
+// DoS prevention: limit cache size to 32MiB (over 1000000 entries on 64-bit
// systems). Due to how we count cache size, actual memory usage is slightly
-// more (~32.25 MB)
-static const unsigned int DEFAULT_MAX_SIG_CACHE_SIZE = 32;
-// Maximum sig cache size allowed
-static const int64_t MAX_MAX_SIG_CACHE_SIZE = 16384;
+// more (~32.25 MiB)
+static constexpr size_t DEFAULT_MAX_SIG_CACHE_BYTES{32 << 20};
class CPubKey;
@@ -33,6 +32,6 @@ public:
bool VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const override;
};
-void InitSignatureCache();
+[[nodiscard]] bool InitSignatureCache(size_t max_size_bytes);
#endif // BITCOIN_SCRIPT_SIGCACHE_H
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 2d569d674a..0d74a661a5 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -146,10 +146,21 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
static bool CreateTaprootScriptSig(const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char>& sig_out, const XOnlyPubKey& pubkey, const uint256& leaf_hash, SigVersion sigversion)
{
+ KeyOriginInfo info;
+ if (provider.GetKeyOriginByXOnly(pubkey, info)) {
+ auto it = sigdata.taproot_misc_pubkeys.find(pubkey);
+ if (it == sigdata.taproot_misc_pubkeys.end()) {
+ sigdata.taproot_misc_pubkeys.emplace(pubkey, std::make_pair(std::set<uint256>({leaf_hash}), info));
+ } else {
+ it->second.first.insert(leaf_hash);
+ }
+ }
+
auto lookup_key = std::make_pair(pubkey, leaf_hash);
auto it = sigdata.taproot_script_sigs.find(lookup_key);
if (it != sigdata.taproot_script_sigs.end()) {
sig_out = it->second;
+ return true;
}
if (creator.CreateSchnorrSig(provider, sig_out, pubkey, &leaf_hash, nullptr, sigversion)) {
sigdata.taproot_script_sigs[lookup_key] = sig_out;
@@ -164,7 +175,7 @@ static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatu
if (leaf_version != TAPROOT_LEAF_TAPSCRIPT) return false;
SigVersion sigversion = SigVersion::TAPSCRIPT;
- uint256 leaf_hash = (CHashWriter(HASHER_TAPLEAF) << uint8_t(leaf_version) << script).GetSHA256();
+ uint256 leaf_hash = (HashWriter{HASHER_TAPLEAF} << uint8_t(leaf_version) << script).GetSHA256();
// <xonly pubkey> OP_CHECKSIG
if (script.size() == 34 && script[33] == OP_CHECKSIG && script[0] == 0x20) {
@@ -205,17 +216,34 @@ static bool SignTaprootScript(const SigningProvider& provider, const BaseSignatu
static bool SignTaproot(const SigningProvider& provider, const BaseSignatureCreator& creator, const WitnessV1Taproot& output, SignatureData& sigdata, std::vector<valtype>& result)
{
TaprootSpendData spenddata;
+ TaprootBuilder builder;
// Gather information about this output.
if (provider.GetTaprootSpendData(output, spenddata)) {
sigdata.tr_spenddata.Merge(spenddata);
}
+ if (provider.GetTaprootBuilder(output, builder)) {
+ sigdata.tr_builder = builder;
+ }
// Try key path spending.
{
+ KeyOriginInfo info;
+ if (provider.GetKeyOriginByXOnly(sigdata.tr_spenddata.internal_key, info)) {
+ auto it = sigdata.taproot_misc_pubkeys.find(sigdata.tr_spenddata.internal_key);
+ if (it == sigdata.taproot_misc_pubkeys.end()) {
+ sigdata.taproot_misc_pubkeys.emplace(sigdata.tr_spenddata.internal_key, std::make_pair(std::set<uint256>(), info));
+ }
+ }
+
std::vector<unsigned char> sig;
if (sigdata.taproot_key_path_sig.size() == 0) {
- if (creator.CreateSchnorrSig(provider, sig, spenddata.internal_key, nullptr, &spenddata.merkle_root, SigVersion::TAPROOT)) {
+ if (creator.CreateSchnorrSig(provider, sig, sigdata.tr_spenddata.internal_key, nullptr, &sigdata.tr_spenddata.merkle_root, SigVersion::TAPROOT)) {
+ sigdata.taproot_key_path_sig = sig;
+ }
+ }
+ if (sigdata.taproot_key_path_sig.size() == 0) {
+ if (creator.CreateSchnorrSig(provider, sig, output, nullptr, nullptr, SigVersion::TAPROOT)) {
sigdata.taproot_key_path_sig = sig;
}
}
@@ -567,8 +595,11 @@ public:
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; }
bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror) const override { return true; }
};
-const DummySignatureChecker DUMMY_CHECKER;
+}
+const BaseSignatureChecker& DUMMY_CHECKER = DummySignatureChecker();
+
+namespace {
class DummySignatureCreator final : public BaseSignatureCreator {
private:
char m_r_len = 32;
@@ -603,25 +634,6 @@ public:
const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator(32, 32);
const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR = DummySignatureCreator(33, 32);
-bool IsSolvable(const SigningProvider& provider, const CScript& script)
-{
- // This check is to make sure that the script we created can actually be solved for and signed by us
- // if we were to have the private keys. This is just to make sure that the script is valid and that,
- // if found in a transaction, we would still accept and relay that transaction. In particular,
- // it will reject witness outputs that require signing with an uncompressed public key.
- SignatureData sigs;
- // Make sure that STANDARD_SCRIPT_VERIFY_FLAGS includes SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, the most
- // important property this function is designed to test for.
- static_assert(STANDARD_SCRIPT_VERIFY_FLAGS & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, "IsSolvable requires standard script flags to include WITNESS_PUBKEYTYPE");
- if (ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, script, sigs)) {
- // VerifyScript check is just defensive, and should never fail.
- bool verified = VerifyScript(sigs.scriptSig, script, &sigs.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, DUMMY_CHECKER);
- assert(verified);
- return true;
- }
- return false;
-}
-
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script)
{
int version;
diff --git a/src/script/sign.h b/src/script/sign.h
index 71203d08ec..813dfe04e3 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -52,6 +52,8 @@ public:
bool CreateSchnorrSig(const SigningProvider& provider, std::vector<unsigned char>& sig, const XOnlyPubKey& pubkey, const uint256* leaf_hash, const uint256* merkle_root, SigVersion sigversion) const override;
};
+/** A signature checker that accepts all signatures */
+extern const BaseSignatureChecker& DUMMY_CHECKER;
/** A signature creator that just produces 71-byte empty signatures. */
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
/** A signature creator that just produces 72-byte empty signatures. */
@@ -70,10 +72,12 @@ struct SignatureData {
CScript witness_script; ///< The witnessScript (if any) for the input. witnessScripts are used in P2WSH outputs.
CScriptWitness scriptWitness; ///< The scriptWitness of an input. Contains complete signatures or the traditional partial signatures format. scriptWitness is part of a transaction input per BIP 144.
TaprootSpendData tr_spenddata; ///< Taproot spending data.
+ std::optional<TaprootBuilder> tr_builder; ///< Taproot tree used to build tr_spenddata.
std::map<CKeyID, SigPair> signatures; ///< BIP 174 style partial signatures for the input. May contain all signatures necessary for producing a final scriptSig or scriptWitness.
std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> misc_pubkeys;
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::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)
@@ -95,12 +99,6 @@ bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom,
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout);
void UpdateInput(CTxIn& input, const SignatureData& data);
-/* Check whether we know how to sign for an output like this, assuming we
- * have all private keys. While this function does not need private keys, the passed
- * provider is used to look up public keys and redeemscripts by hash.
- * Solvability is unrelated to whether we consider this output to be ours. */
-bool IsSolvable(const SigningProvider& provider, const CScript& script);
-
/** Check whether a scriptPubKey is known to be segwit. */
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script);
diff --git a/src/script/signingprovider.cpp b/src/script/signingprovider.cpp
index 552934e0eb..a82a8b252a 100644
--- a/src/script/signingprovider.cpp
+++ b/src/script/signingprovider.cpp
@@ -48,6 +48,10 @@ bool HidingSigningProvider::GetTaprootSpendData(const XOnlyPubKey& output_key, T
{
return m_provider->GetTaprootSpendData(output_key, spenddata);
}
+bool HidingSigningProvider::GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const
+{
+ return m_provider->GetTaprootBuilder(output_key, builder);
+}
bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
@@ -61,25 +65,26 @@ bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info)
bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
bool FlatSigningProvider::GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const
{
- return LookupHelper(tr_spenddata, output_key, spenddata);
+ TaprootBuilder builder;
+ if (LookupHelper(tr_trees, output_key, builder)) {
+ spenddata = builder.GetSpendData();
+ return true;
+ }
+ return false;
+}
+bool FlatSigningProvider::GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const
+{
+ return LookupHelper(tr_trees, output_key, builder);
}
-FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b)
+FlatSigningProvider& FlatSigningProvider::Merge(FlatSigningProvider&& b)
{
- FlatSigningProvider ret;
- ret.scripts = a.scripts;
- ret.scripts.insert(b.scripts.begin(), b.scripts.end());
- ret.pubkeys = a.pubkeys;
- ret.pubkeys.insert(b.pubkeys.begin(), b.pubkeys.end());
- ret.keys = a.keys;
- ret.keys.insert(b.keys.begin(), b.keys.end());
- ret.origins = a.origins;
- ret.origins.insert(b.origins.begin(), b.origins.end());
- ret.tr_spenddata = a.tr_spenddata;
- for (const auto& [output_key, spenddata] : b.tr_spenddata) {
- ret.tr_spenddata[output_key].Merge(spenddata);
- }
- return ret;
+ scripts.merge(b.scripts);
+ pubkeys.merge(b.pubkeys);
+ keys.merge(b.keys);
+ origins.merge(b.origins);
+ tr_trees.merge(b.tr_trees);
+ return *this;
}
void FillableSigningProvider::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
diff --git a/src/script/signingprovider.h b/src/script/signingprovider.h
index f1bded1a8c..2d4234ea0b 100644
--- a/src/script/signingprovider.h
+++ b/src/script/signingprovider.h
@@ -6,6 +6,7 @@
#ifndef BITCOIN_SCRIPT_SIGNINGPROVIDER_H
#define BITCOIN_SCRIPT_SIGNINGPROVIDER_H
+#include <attributes.h>
#include <key.h>
#include <pubkey.h>
#include <script/keyorigin.h>
@@ -25,6 +26,7 @@ public:
virtual bool HaveKey(const CKeyID &address) const { return false; }
virtual bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return false; }
virtual bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const { return false; }
+ virtual bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const { return false; }
bool GetKeyByXOnly(const XOnlyPubKey& pubkey, CKey& key) const
{
@@ -67,6 +69,7 @@ public:
bool GetKey(const CKeyID& keyid, CKey& key) const override;
bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override;
+ bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override;
};
struct FlatSigningProvider final : public SigningProvider
@@ -75,16 +78,17 @@ struct FlatSigningProvider final : public SigningProvider
std::map<CKeyID, CPubKey> pubkeys;
std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> origins;
std::map<CKeyID, CKey> keys;
- std::map<XOnlyPubKey, TaprootSpendData> tr_spenddata; /** Map from output key to spend data. */
+ std::map<XOnlyPubKey, TaprootBuilder> tr_trees; /** Map from output key to Taproot tree (which can then make the TaprootSpendData */
bool GetCScript(const CScriptID& scriptid, CScript& script) const override;
bool GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const override;
bool GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const override;
bool GetKey(const CKeyID& keyid, CKey& key) const override;
bool GetTaprootSpendData(const XOnlyPubKey& output_key, TaprootSpendData& spenddata) const override;
-};
+ bool GetTaprootBuilder(const XOnlyPubKey& output_key, TaprootBuilder& builder) const override;
-FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b);
+ FlatSigningProvider& Merge(FlatSigningProvider&& b) LIFETIMEBOUND;
+};
/** Fillable signing provider that keeps keys in an address->secret map */
class FillableSigningProvider : public SigningProvider
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index e25155d3dd..6101738061 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -16,9 +16,6 @@
typedef std::vector<unsigned char> valtype;
-bool fAcceptDatacarrier = DEFAULT_ACCEPT_DATACARRIER;
-unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
-
CScriptID::CScriptID(const CScript& in) : BaseHash(Hash160(in)) {}
CScriptID::CScriptID(const ScriptHash& in) : BaseHash(static_cast<uint160>(in)) {}
@@ -375,9 +372,9 @@ bool IsValidDestination(const CTxDestination& dest) {
}
/* Lexicographically sort a and b's hash, and compute parent hash. */
if (a.hash < b.hash) {
- ret.hash = (CHashWriter(HASHER_TAPBRANCH) << a.hash << b.hash).GetSHA256();
+ ret.hash = (HashWriter{HASHER_TAPBRANCH} << a.hash << b.hash).GetSHA256();
} else {
- ret.hash = (CHashWriter(HASHER_TAPBRANCH) << b.hash << a.hash).GetSHA256();
+ ret.hash = (HashWriter{HASHER_TAPBRANCH} << b.hash << a.hash).GetSHA256();
}
return ret;
}
@@ -452,7 +449,7 @@ TaprootBuilder& TaprootBuilder::Add(int depth, const CScript& script, int leaf_v
if (!IsValid()) return *this;
/* Construct NodeInfo object with leaf hash and (if track is true) also leaf information. */
NodeInfo node;
- node.hash = (CHashWriter{HASHER_TAPLEAF} << uint8_t(leaf_version) << script).GetSHA256();
+ node.hash = (HashWriter{HASHER_TAPLEAF} << uint8_t(leaf_version) << script).GetSHA256();
if (track) node.leaves.emplace_back(LeafInfo{script, leaf_version, {}});
/* Insert into the branch. */
Insert(std::move(node), depth);
@@ -485,6 +482,7 @@ WitnessV1Taproot TaprootBuilder::GetOutput() { return WitnessV1Taproot{m_output_
TaprootSpendData TaprootBuilder::GetSpendData() const
{
assert(IsComplete());
+ assert(m_output_key.IsFullyValid());
TaprootSpendData spd;
spd.merkle_root = m_branch.size() == 0 ? uint256() : m_branch[0]->hash;
spd.internal_key = m_internal_key;
@@ -609,7 +607,7 @@ std::optional<std::vector<std::tuple<int, CScript, int>>> InferTaprootTree(const
node.done = true;
stack.pop_back();
} else if (node.sub[0]->done && !node.sub[1]->done && !node.sub[1]->explored && !node.sub[1]->hash.IsNull() &&
- (CHashWriter{HASHER_TAPBRANCH} << node.sub[1]->hash << node.sub[1]->hash).GetSHA256() == node.hash) {
+ (HashWriter{HASHER_TAPBRANCH} << node.sub[1]->hash << node.sub[1]->hash).GetSHA256() == node.hash) {
// Whenever there are nodes with two identical subtrees under it, we run into a problem:
// the control blocks for the leaves underneath those will be identical as well, and thus
// they will all be matched to the same path in the tree. The result is that at the location
@@ -642,3 +640,19 @@ std::optional<std::vector<std::tuple<int, CScript, int>>> InferTaprootTree(const
return ret;
}
+
+std::vector<std::tuple<uint8_t, uint8_t, CScript>> TaprootBuilder::GetTreeTuples() const
+{
+ assert(IsComplete());
+ std::vector<std::tuple<uint8_t, uint8_t, CScript>> tuples;
+ if (m_branch.size()) {
+ const auto& leaves = m_branch[0]->leaves;
+ for (const auto& leaf : leaves) {
+ 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));
+ }
+ }
+ return tuples;
+}
diff --git a/src/script/standard.h b/src/script/standard.h
index 6a15ba4e3d..966a52b2c7 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -33,21 +33,12 @@ public:
};
/**
- * Default setting for nMaxDatacarrierBytes. 80 bytes of data, +1 for OP_RETURN,
+ * Default setting for -datacarriersize. 80 bytes of data, +1 for OP_RETURN,
* +2 for the pushdata opcodes.
*/
static const unsigned int MAX_OP_RETURN_RELAY = 83;
/**
- * A data carrying output is an unspendable output containing data. The script
- * type is designated as TxoutType::NULL_DATA.
- */
-extern bool fAcceptDatacarrier;
-
-/** Maximum size of TxoutType::NULL_DATA scripts that this node considers standard. */
-extern unsigned nMaxDatacarrierBytes;
-
-/**
* Mandatory script verification flags that all new blocks must comply with for
* them to be valid. (but old blocks may not comply with) Currently just P2SH,
* but in the future other flags may be added.
@@ -322,6 +313,10 @@ public:
static bool ValidDepths(const std::vector<int>& depths);
/** Compute spending data (after Finalize()). */
TaprootSpendData GetSpendData() const;
+ /** Returns a vector of tuples representing the depth, leaf version, and script */
+ std::vector<std::tuple<uint8_t, uint8_t, CScript>> GetTreeTuples() const;
+ /** Returns true if there are any tapscripts */
+ bool HasScripts() const { return !m_branch.empty(); }
};
/** Given a TaprootSpendData and the output key, reconstruct its script tree.
diff --git a/src/serialize.h b/src/serialize.h
index a1cce78451..89a9f32240 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -520,6 +520,29 @@ struct CompactSizeFormatter
}
};
+template <typename U, bool LOSSY = false>
+struct ChronoFormatter {
+ template <typename Stream, typename Tp>
+ void Unser(Stream& s, Tp& tp)
+ {
+ U u;
+ s >> u;
+ // Lossy deserialization does not make sense, so force Wnarrowing
+ tp = Tp{typename Tp::duration{typename Tp::duration::rep{u}}};
+ }
+ template <typename Stream, typename Tp>
+ void Ser(Stream& s, Tp tp)
+ {
+ if constexpr (LOSSY) {
+ s << U(tp.time_since_epoch().count());
+ } else {
+ s << U{tp.time_since_epoch().count()};
+ }
+ }
+};
+template <typename U>
+using LossyChronoFormatter = ChronoFormatter<U, true>;
+
class CompactSizeWriter
{
protected:
diff --git a/src/streams.h b/src/streams.h
index 96b7696f72..f14d347380 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -465,35 +465,28 @@ public:
};
-
/** Non-refcounted RAII wrapper for FILE*
*
* Will automatically close the file when it goes out of scope if not null.
* If you're returning the file pointer, return file.release().
* If you need to close the file early, use file.fclose() instead of fclose(file).
*/
-class CAutoFile
+class AutoFile
{
-private:
- const int nType;
- const int nVersion;
-
+protected:
FILE* file;
public:
- CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn)
- {
- file = filenew;
- }
+ explicit AutoFile(FILE* filenew) : file{filenew} {}
- ~CAutoFile()
+ ~AutoFile()
{
fclose();
}
// Disallow copies
- CAutoFile(const CAutoFile&) = delete;
- CAutoFile& operator=(const CAutoFile&) = delete;
+ AutoFile(const AutoFile&) = delete;
+ AutoFile& operator=(const AutoFile&) = delete;
void fclose()
{
@@ -504,14 +497,14 @@ public:
}
/** Get wrapped FILE* with transfer of ownership.
- * @note This will invalidate the CAutoFile object, and makes it the responsibility of the caller
+ * @note This will invalidate the AutoFile object, and makes it the responsibility of the caller
* of this function to clean up the returned FILE*.
*/
FILE* release() { FILE* ret = file; file = nullptr; return ret; }
/** Get wrapped FILE* without transfer of ownership.
* @note Ownership of the FILE* will remain with this class. Use this only if the scope of the
- * CAutoFile outlives use of the passed pointer.
+ * AutoFile outlives use of the passed pointer.
*/
FILE* Get() const { return file; }
@@ -522,40 +515,62 @@ public:
//
// Stream subset
//
- int GetType() const { return nType; }
- int GetVersion() const { return nVersion; }
-
void read(Span<std::byte> dst)
{
- if (!file)
- throw std::ios_base::failure("CAutoFile::read: file handle is nullptr");
+ if (!file) throw std::ios_base::failure("AutoFile::read: file handle is nullptr");
if (fread(dst.data(), 1, dst.size(), file) != dst.size()) {
- throw std::ios_base::failure(feof(file) ? "CAutoFile::read: end of file" : "CAutoFile::read: fread failed");
+ throw std::ios_base::failure(feof(file) ? "AutoFile::read: end of file" : "AutoFile::read: fread failed");
}
}
void ignore(size_t nSize)
{
- if (!file)
- throw std::ios_base::failure("CAutoFile::ignore: file handle is nullptr");
+ if (!file) throw std::ios_base::failure("AutoFile::ignore: file handle is nullptr");
unsigned char data[4096];
while (nSize > 0) {
size_t nNow = std::min<size_t>(nSize, sizeof(data));
if (fread(data, 1, nNow, file) != nNow)
- throw std::ios_base::failure(feof(file) ? "CAutoFile::ignore: end of file" : "CAutoFile::read: fread failed");
+ throw std::ios_base::failure(feof(file) ? "AutoFile::ignore: end of file" : "AutoFile::read: fread failed");
nSize -= nNow;
}
}
void write(Span<const std::byte> src)
{
- if (!file)
- throw std::ios_base::failure("CAutoFile::write: file handle is nullptr");
+ if (!file) throw std::ios_base::failure("AutoFile::write: file handle is nullptr");
if (fwrite(src.data(), 1, src.size(), file) != src.size()) {
- throw std::ios_base::failure("CAutoFile::write: write failed");
+ throw std::ios_base::failure("AutoFile::write: write failed");
}
}
+ template <typename T>
+ AutoFile& operator<<(const T& obj)
+ {
+ if (!file) throw std::ios_base::failure("AutoFile::operator<<: file handle is nullptr");
+ ::Serialize(*this, obj);
+ return *this;
+ }
+
+ template <typename T>
+ AutoFile& operator>>(T&& obj)
+ {
+ if (!file) throw std::ios_base::failure("AutoFile::operator>>: file handle is nullptr");
+ ::Unserialize(*this, obj);
+ return *this;
+ }
+};
+
+class CAutoFile : public AutoFile
+{
+private:
+ const int nType;
+ const int nVersion;
+
+public:
+ CAutoFile(FILE* filenew, int nTypeIn, int nVersionIn) : AutoFile{filenew}, nType(nTypeIn), nVersion(nVersionIn) {}
+ int GetType() const { return nType; }
+ int GetVersion() const { return nVersion; }
+
template<typename T>
CAutoFile& operator<<(const T& obj)
{
diff --git a/src/sync.h b/src/sync.h
index 7ec4b668ac..c34d969041 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -261,7 +261,7 @@ inline RecursiveMutex* MaybeCheckNotHeld(RecursiveMutex* cs) LOCKS_EXCLUDED(cs)
#define LOCK(cs) DebugLock<decltype(cs)> UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
#define LOCK2(cs1, cs2) \
DebugLock<decltype(cs1)> criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \
- DebugLock<decltype(cs2)> criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__);
+ DebugLock<decltype(cs2)> criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__)
#define TRY_LOCK(cs, name) DebugLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__, true)
#define WAIT_LOCK(cs, name) DebugLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 12cf1176a6..b10d32ccec 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
CAddress addr{CAddress(ResolveService("253.3.3.3", 8333), NODE_NONE)};
- int64_t start_time{GetAdjustedTime()};
+ const auto start_time{Now<NodeSeconds>()};
addr.nTime = start_time;
// test that multiplicity stays at 1 if nTime doesn't increase
@@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
for (unsigned int i = 1; i < 400; ++i) {
std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};
CNetAddr source{ResolveIP(addr_ip)};
- addr.nTime = start_time + i;
+ addr.nTime = start_time + std::chrono::seconds{i};
addrman->Add({addr}, source);
}
AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();
@@ -295,15 +295,15 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
- addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
+ addr1.nTime = Now<NodeSeconds>(); // Set time so isTerrible = false
CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
- addr2.nTime = GetAdjustedTime();
+ addr2.nTime = Now<NodeSeconds>();
CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
- addr3.nTime = GetAdjustedTime();
+ addr3.nTime = Now<NodeSeconds>();
CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
- addr4.nTime = GetAdjustedTime();
+ addr4.nTime = Now<NodeSeconds>();
CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
- addr5.nTime = GetAdjustedTime();
+ addr5.nTime = Now<NodeSeconds>();
CNetAddr source1 = ResolveIP("250.1.2.1");
CNetAddr source2 = ResolveIP("250.2.3.3");
@@ -329,7 +329,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
// Ensure that for all addrs in addrman, isTerrible == false.
- addr.nTime = GetAdjustedTime();
+ addr.nTime = Now<NodeSeconds>();
addrman->Add({addr}, ResolveIP(strAddr));
if (i % 8 == 0)
addrman->Good(addr);
@@ -821,8 +821,8 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
// Ensure test of address fails, so that it is evicted.
// Update entry in tried by setting last good connection in the deep past.
- BOOST_CHECK(!addrman->Good(info, /*nTime=*/1));
- addrman->Attempt(info, /*fCountFailure=*/false, /*nTime=*/GetAdjustedTime() - 61);
+ BOOST_CHECK(!addrman->Good(info, NodeSeconds{1s}));
+ addrman->Attempt(info, /*fCountFailure=*/false, Now<NodeSeconds>() - 61s);
// Should swap 36 for 19.
addrman->ResolveCollisions();
@@ -966,7 +966,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
CNetAddr source{ResolveIP("252.2.2.2")};
CAddress addr{CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE)};
- int64_t start_time{GetAdjustedTime() - 10000};
+ const auto start_time{Now<NodeSeconds>() - 10000s};
addr.nTime = start_time;
BOOST_CHECK(addrman->Add({addr}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
@@ -978,7 +978,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
addrman->SetServices(addr_diff_port, NODE_NETWORK_LIMITED);
std::vector<CAddress> vAddr1{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
BOOST_CHECK_EQUAL(vAddr1.size(), 1U);
- BOOST_CHECK_EQUAL(vAddr1.at(0).nTime, start_time);
+ BOOST_CHECK(vAddr1.at(0).nTime == start_time);
BOOST_CHECK_EQUAL(vAddr1.at(0).nServices, NODE_NONE);
// Updating an addrman entry with the correct port is successful
@@ -986,7 +986,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
addrman->SetServices(addr, NODE_NETWORK_LIMITED);
std::vector<CAddress> vAddr2 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
BOOST_CHECK_EQUAL(vAddr2.size(), 1U);
- BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000);
+ BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000s);
BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
}
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 00f32ddcee..249f89ae2f 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -25,7 +25,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
{
UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
if (test.size() < 2) // Allow for extra stuff (useful for comments)
{
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
std::vector<unsigned char> result;
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
if (test.size() < 2) // Allow for extra stuff (useful for comments)
{
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 64cc924239..75b29ae0aa 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -184,4 +184,22 @@ BOOST_AUTO_TEST_CASE(bip32_test5) {
}
}
+BOOST_AUTO_TEST_CASE(bip32_max_depth) {
+ CExtKey key_parent{DecodeExtKey(test1.vDerive[0].prv)}, key_child;
+ CExtPubKey pubkey_parent{DecodeExtPubKey(test1.vDerive[0].pub)}, pubkey_child;
+
+ // We can derive up to the 255th depth..
+ for (auto i = 0; i++ < 255;) {
+ BOOST_CHECK(key_parent.Derive(key_child, 0));
+ std::swap(key_parent, key_child);
+ BOOST_CHECK(pubkey_parent.Derive(pubkey_child, 0));
+ std::swap(pubkey_parent, pubkey_child);
+ }
+
+ // But trying to derive a non-existent 256th depth will fail!
+ BOOST_CHECK(key_parent.nDepth == 255 && pubkey_parent.nDepth == 255);
+ BOOST_CHECK(!key_parent.Derive(key_child, 0));
+ BOOST_CHECK(!pubkey_parent.Derive(pubkey_child, 0));
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
index c31e4e51f7..2798e998af 100644
--- a/src/test/blockfilter_index_tests.cpp
+++ b/src/test/blockfilter_index_tests.cpp
@@ -7,6 +7,7 @@
#include <consensus/merkle.h>
#include <consensus/validation.h>
#include <index/blockfilterindex.h>
+#include <interfaces/chain.h>
#include <node/miner.h>
#include <pow.h>
#include <script/standard.h>
@@ -100,7 +101,7 @@ bool BuildChainTestingSetup::BuildChain(const CBlockIndex* pindex,
CBlockHeader header = block->GetBlockHeader();
BlockValidationState state;
- if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, &pindex)) {
+ if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, true, state, &pindex)) {
return false;
}
}
@@ -110,7 +111,7 @@ bool BuildChainTestingSetup::BuildChain(const CBlockIndex* pindex,
BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
{
- BlockFilterIndex filter_index(BlockFilterType::BASIC, 1 << 20, true);
+ BlockFilterIndex filter_index(interfaces::MakeChain(m_node), BlockFilterType::BASIC, 1 << 20, true);
uint256 last_header;
@@ -137,7 +138,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
// BlockUntilSyncedToCurrentChain should return false before index is started.
BOOST_CHECK(!filter_index.BlockUntilSyncedToCurrentChain());
- BOOST_REQUIRE(filter_index.Start(m_node.chainman->ActiveChainstate()));
+ BOOST_REQUIRE(filter_index.Start());
// Allow filter index to catch up with the block index.
constexpr int64_t timeout_ms = 10 * 1000;
@@ -177,7 +178,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
uint256 chainA_last_header = last_header;
for (size_t i = 0; i < 2; i++) {
const auto& block = chainA[i];
- BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr));
+ BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, true, nullptr));
}
for (size_t i = 0; i < 2; i++) {
const auto& block = chainA[i];
@@ -195,7 +196,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
uint256 chainB_last_header = last_header;
for (size_t i = 0; i < 3; i++) {
const auto& block = chainB[i];
- BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr));
+ BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, true, nullptr));
}
for (size_t i = 0; i < 3; i++) {
const auto& block = chainB[i];
@@ -226,7 +227,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
// Reorg back to chain A.
for (size_t i = 2; i < 4; i++) {
const auto& block = chainA[i];
- BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr));
+ BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, true, nullptr));
}
// Check that chain A and B blocks can be retrieved.
@@ -279,14 +280,14 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_init_destroy, BasicTestingSetup)
filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
BOOST_CHECK(filter_index == nullptr);
- BOOST_CHECK(InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+ BOOST_CHECK(InitBlockFilterIndex([&]{ return interfaces::MakeChain(m_node); }, BlockFilterType::BASIC, 1 << 20, true, false));
filter_index = GetBlockFilterIndex(BlockFilterType::BASIC);
BOOST_CHECK(filter_index != nullptr);
BOOST_CHECK(filter_index->GetFilterType() == BlockFilterType::BASIC);
// Initialize returns false if index already exists.
- BOOST_CHECK(!InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+ BOOST_CHECK(!InitBlockFilterIndex([&]{ return interfaces::MakeChain(m_node); }, BlockFilterType::BASIC, 1 << 20, true, false));
int iter_count = 0;
ForEachBlockFilterIndex([&iter_count](BlockFilterIndex& _index) { iter_count++; });
@@ -301,7 +302,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_init_destroy, BasicTestingSetup)
BOOST_CHECK(filter_index == nullptr);
// Reinitialize index.
- BOOST_CHECK(InitBlockFilterIndex(BlockFilterType::BASIC, 1 << 20, true, false));
+ BOOST_CHECK(InitBlockFilterIndex([&]{ return interfaces::MakeChain(m_node); }, BlockFilterType::BASIC, 1 << 20, true, false));
DestroyAllBlockFilterIndexes();
diff --git a/src/test/blockfilter_tests.cpp b/src/test/blockfilter_tests.cpp
index 178757e7b4..0831188327 100644
--- a/src/test/blockfilter_tests.cpp
+++ b/src/test/blockfilter_tests.cpp
@@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(blockfilters_json_test)
const UniValue& tests = json.get_array();
for (unsigned int i = 0; i < tests.size(); i++) {
- UniValue test = tests[i];
+ const UniValue& test = tests[i];
std::string strTest = test.write();
if (test.size() == 1) {
diff --git a/src/test/coinstatsindex_tests.cpp b/src/test/coinstatsindex_tests.cpp
index 50eb479035..2a6a777cfe 100644
--- a/src/test/coinstatsindex_tests.cpp
+++ b/src/test/coinstatsindex_tests.cpp
@@ -4,6 +4,8 @@
#include <chainparams.h>
#include <index/coinstatsindex.h>
+#include <interfaces/chain.h>
+#include <kernel/coinstats.h>
#include <test/util/setup_common.h>
#include <test/util/validation.h>
#include <util/time.h>
@@ -13,9 +15,6 @@
#include <chrono>
-using kernel::CCoinsStats;
-using kernel::CoinStatsHashType;
-
BOOST_AUTO_TEST_SUITE(coinstatsindex_tests)
static void IndexWaitSynced(BaseIndex& index)
@@ -31,7 +30,7 @@ static void IndexWaitSynced(BaseIndex& index)
BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
{
- CoinStatsIndex coin_stats_index{1 << 20, true};
+ CoinStatsIndex coin_stats_index{interfaces::MakeChain(m_node), 1 << 20, true};
const CBlockIndex* block_index;
{
@@ -40,13 +39,13 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
}
// CoinStatsIndex should not be found before it is started.
- BOOST_CHECK(!coin_stats_index.LookUpStats(block_index));
+ BOOST_CHECK(!coin_stats_index.LookUpStats(*block_index));
// BlockUntilSyncedToCurrentChain should return false before CoinStatsIndex
// is started.
BOOST_CHECK(!coin_stats_index.BlockUntilSyncedToCurrentChain());
- BOOST_REQUIRE(coin_stats_index.Start(m_node.chainman->ActiveChainstate()));
+ BOOST_REQUIRE(coin_stats_index.Start());
IndexWaitSynced(coin_stats_index);
@@ -56,10 +55,10 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
LOCK(cs_main);
genesis_block_index = m_node.chainman->ActiveChain().Genesis();
}
- BOOST_CHECK(coin_stats_index.LookUpStats(genesis_block_index));
+ BOOST_CHECK(coin_stats_index.LookUpStats(*genesis_block_index));
// Check that CoinStatsIndex updates with new blocks.
- BOOST_CHECK(coin_stats_index.LookUpStats(block_index));
+ BOOST_CHECK(coin_stats_index.LookUpStats(*block_index));
const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
std::vector<CMutableTransaction> noTxns;
@@ -73,7 +72,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
LOCK(cs_main);
new_block_index = m_node.chainman->ActiveChain().Tip();
}
- BOOST_CHECK(coin_stats_index.LookUpStats(new_block_index));
+ BOOST_CHECK(coin_stats_index.LookUpStats(*new_block_index));
BOOST_CHECK(block_index != new_block_index);
@@ -87,11 +86,11 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
// make sure index is not corrupted and is able to reload.
BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
{
- CChainState& chainstate = Assert(m_node.chainman)->ActiveChainstate();
+ Chainstate& chainstate = Assert(m_node.chainman)->ActiveChainstate();
const CChainParams& params = Params();
{
- CoinStatsIndex index{1 << 20};
- BOOST_REQUIRE(index.Start(chainstate));
+ CoinStatsIndex index{interfaces::MakeChain(m_node), 1 << 20};
+ BOOST_REQUIRE(index.Start());
IndexWaitSynced(index);
std::shared_ptr<const CBlock> new_block;
CBlockIndex* new_block_index = nullptr;
@@ -104,7 +103,7 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
LOCK(cs_main);
BlockValidationState state;
BOOST_CHECK(CheckBlock(block, state, params.GetConsensus()));
- BOOST_CHECK(chainstate.AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr));
+ BOOST_CHECK(chainstate.AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr, true));
CCoinsViewCache view(&chainstate.CoinsTip());
BOOST_CHECK(chainstate.ConnectBlock(block, state, new_block_index, view));
}
@@ -116,9 +115,9 @@ BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
}
{
- CoinStatsIndex index{1 << 20};
+ CoinStatsIndex index{interfaces::MakeChain(m_node), 1 << 20};
// Make sure the index can be loaded.
- BOOST_REQUIRE(index.Start(chainstate));
+ BOOST_REQUIRE(index.Start());
index.Stop();
}
}
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index 3b4a6f2637..7889156d51 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -15,6 +15,7 @@
#include <serialize.h>
#include <test/util/net.h>
#include <test/util/setup_common.h>
+#include <timedata.h>
#include <util/string.h>
#include <util/system.h>
#include <util/time.h>
@@ -44,17 +45,15 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
// work.
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
- auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman);
+ ConnmanTestMsg& connman = static_cast<ConnmanTestMsg&>(*m_node.connman);
// Disable inactivity checks for this test to avoid interference
- static_cast<ConnmanTestMsg*>(connman.get())->SetPeerConnectTimeout(99999s);
- auto peerLogic = PeerManager::make(*connman, *m_node.addrman, nullptr,
- *m_node.chainman, *m_node.mempool, false);
+ connman.SetPeerConnectTimeout(99999s);
+ PeerManager& peerman = *m_node.peerman;
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
NodeId id{0};
CNode dummyNode1{id++,
- ServiceFlags(NODE_NETWORK | NODE_WITNESS),
/*sock=*/nullptr,
addr1,
/*nKeyedNetGroupIn=*/0,
@@ -63,10 +62,15 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
/*addrNameIn=*/"",
ConnectionType::OUTBOUND_FULL_RELAY,
/*inbound_onion=*/false};
- dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
- peerLogic->InitializeNode(&dummyNode1);
- dummyNode1.fSuccessfullyConnected = true;
+ connman.Handshake(
+ /*node=*/dummyNode1,
+ /*successfully_connected=*/true,
+ /*remote_services=*/ServiceFlags(NODE_NETWORK | NODE_WITNESS),
+ /*local_services=*/ServiceFlags(NODE_NETWORK | NODE_WITNESS),
+ /*version=*/PROTOCOL_VERSION,
+ /*relay_txs=*/true);
+ TestOnlyResetTimeData();
// This test requires that we have a chain with non-zero work.
{
@@ -78,7 +82,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
// Test starts here
{
LOCK(dummyNode1.cs_sendProcessing);
- BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
+ BOOST_CHECK(peerman.SendMessages(&dummyNode1)); // should result in getheaders
}
{
LOCK(dummyNode1.cs_vSend);
@@ -91,7 +95,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(nStartTime+21*60);
{
LOCK(dummyNode1.cs_sendProcessing);
- BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in getheaders
+ BOOST_CHECK(peerman.SendMessages(&dummyNode1)); // should result in getheaders
}
{
LOCK(dummyNode1.cs_vSend);
@@ -101,18 +105,17 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(nStartTime+24*60);
{
LOCK(dummyNode1.cs_sendProcessing);
- BOOST_CHECK(peerLogic->SendMessages(&dummyNode1)); // should result in disconnect
+ BOOST_CHECK(peerman.SendMessages(&dummyNode1)); // should result in disconnect
}
BOOST_CHECK(dummyNode1.fDisconnect == true);
- peerLogic->FinalizeNode(dummyNode1);
+ peerman.FinalizeNode(dummyNode1);
}
static void AddRandomOutboundPeer(NodeId& id, std::vector<CNode*>& vNodes, PeerManager& peerLogic, ConnmanTestMsg& connman, ConnectionType connType)
{
CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
vNodes.emplace_back(new CNode{id++,
- ServiceFlags(NODE_NETWORK | NODE_WITNESS),
/*sock=*/nullptr,
addr,
/*nKeyedNetGroupIn=*/0,
@@ -124,7 +127,7 @@ static void AddRandomOutboundPeer(NodeId& id, std::vector<CNode*>& vNodes, PeerM
CNode &node = *vNodes.back();
node.SetCommonVersion(PROTOCOL_VERSION);
- peerLogic.InitializeNode(&node);
+ peerLogic.InitializeNode(node, ServiceFlags(NODE_NETWORK | NODE_WITNESS));
node.fSuccessfullyConnected = true;
connman.AddTestNode(node);
@@ -292,7 +295,6 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
banman->ClearBanned();
NodeId id{0};
nodes[0] = new CNode{id++,
- NODE_NETWORK,
/*sock=*/nullptr,
addr[0],
/*nKeyedNetGroupIn=*/0,
@@ -302,10 +304,10 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
ConnectionType::INBOUND,
/*inbound_onion=*/false};
nodes[0]->SetCommonVersion(PROTOCOL_VERSION);
- peerLogic->InitializeNode(nodes[0]);
+ peerLogic->InitializeNode(*nodes[0], NODE_NETWORK);
nodes[0]->fSuccessfullyConnected = true;
connman->AddTestNode(*nodes[0]);
- peerLogic->Misbehaving(nodes[0]->GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/""); // Should be discouraged
+ peerLogic->UnitTestMisbehaving(nodes[0]->GetId(), DISCOURAGEMENT_THRESHOLD); // Should be discouraged
{
LOCK(nodes[0]->cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(nodes[0]));
@@ -315,7 +317,6 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
BOOST_CHECK(!banman->IsDiscouraged(other_addr)); // Different address, not discouraged
nodes[1] = new CNode{id++,
- NODE_NETWORK,
/*sock=*/nullptr,
addr[1],
/*nKeyedNetGroupIn=*/1,
@@ -325,10 +326,10 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
ConnectionType::INBOUND,
/*inbound_onion=*/false};
nodes[1]->SetCommonVersion(PROTOCOL_VERSION);
- peerLogic->InitializeNode(nodes[1]);
+ peerLogic->InitializeNode(*nodes[1], NODE_NETWORK);
nodes[1]->fSuccessfullyConnected = true;
connman->AddTestNode(*nodes[1]);
- peerLogic->Misbehaving(nodes[1]->GetId(), DISCOURAGEMENT_THRESHOLD - 1, /*message=*/"");
+ peerLogic->UnitTestMisbehaving(nodes[1]->GetId(), DISCOURAGEMENT_THRESHOLD - 1);
{
LOCK(nodes[1]->cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
@@ -339,7 +340,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
// [1] is not discouraged/disconnected yet.
BOOST_CHECK(!banman->IsDiscouraged(addr[1]));
BOOST_CHECK(!nodes[1]->fDisconnect);
- peerLogic->Misbehaving(nodes[1]->GetId(), 1, /*message=*/""); // [1] reaches discouragement threshold
+ peerLogic->UnitTestMisbehaving(nodes[1]->GetId(), 1); // [1] reaches discouragement threshold
{
LOCK(nodes[1]->cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(nodes[1]));
@@ -353,7 +354,6 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
// Make sure non-IP peers are discouraged and disconnected properly.
nodes[2] = new CNode{id++,
- NODE_NETWORK,
/*sock=*/nullptr,
addr[2],
/*nKeyedNetGroupIn=*/1,
@@ -363,10 +363,10 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
ConnectionType::OUTBOUND_FULL_RELAY,
/*inbound_onion=*/false};
nodes[2]->SetCommonVersion(PROTOCOL_VERSION);
- peerLogic->InitializeNode(nodes[2]);
+ peerLogic->InitializeNode(*nodes[2], NODE_NETWORK);
nodes[2]->fSuccessfullyConnected = true;
connman->AddTestNode(*nodes[2]);
- peerLogic->Misbehaving(nodes[2]->GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/"");
+ peerLogic->UnitTestMisbehaving(nodes[2]->GetId(), DISCOURAGEMENT_THRESHOLD);
{
LOCK(nodes[2]->cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(nodes[2]));
@@ -398,7 +398,6 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
CAddress addr(ip(0xa0b0c001), NODE_NONE);
NodeId id{0};
CNode dummyNode{id++,
- NODE_NETWORK,
/*sock=*/nullptr,
addr,
/*nKeyedNetGroupIn=*/4,
@@ -408,10 +407,10 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
ConnectionType::INBOUND,
/*inbound_onion=*/false};
dummyNode.SetCommonVersion(PROTOCOL_VERSION);
- peerLogic->InitializeNode(&dummyNode);
+ peerLogic->InitializeNode(dummyNode, NODE_NETWORK);
dummyNode.fSuccessfullyConnected = true;
- peerLogic->Misbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD, /*message=*/"");
+ peerLogic->UnitTestMisbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD);
{
LOCK(dummyNode.cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index 63c86a896d..6b2ef74e19 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -126,7 +126,7 @@ std::set<std::pair<CPubKey, KeyOriginInfo>> GetKeyOriginData(const FlatSigningPr
return ret;
}
-void DoCheck(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY,
+void DoCheck(const std::string& prv, const std::string& pub, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY,
bool replace_apostrophe_with_h_in_prv=false, bool replace_apostrophe_with_h_in_pub=false)
{
FlatSigningProvider keys_priv, keys_pub;
@@ -141,14 +141,13 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
} else {
parse_priv = Parse(prv, keys_priv, error);
}
+ BOOST_CHECK_MESSAGE(parse_priv, error);
if (replace_apostrophe_with_h_in_pub) {
parse_pub = Parse(UseHInsteadOfApostrophe(pub), keys_pub, error);
} else {
parse_pub = Parse(pub, keys_pub, error);
}
-
- BOOST_CHECK(parse_priv);
- BOOST_CHECK(parse_pub);
+ BOOST_CHECK_MESSAGE(parse_pub, error);
// Check that the correct OutputType is inferred
BOOST_CHECK(parse_priv->GetOutputType() == type);
@@ -161,8 +160,8 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
// Check that both versions serialize back to the public version.
std::string pub1 = parse_priv->ToString();
std::string pub2 = parse_pub->ToString();
- BOOST_CHECK(EqualDescriptor(pub, pub1));
- BOOST_CHECK(EqualDescriptor(pub, pub2));
+ BOOST_CHECK_MESSAGE(EqualDescriptor(pub, pub1), "Private ser: " + pub1 + " Public desc: " + pub);
+ BOOST_CHECK_MESSAGE(EqualDescriptor(pub, pub2), "Public ser: " + pub2 + " Public desc: " + pub);
// Check that both can be serialized with private key back to the private version, but not without private key.
if (!(flags & MISSING_PRIVKEYS)) {
@@ -234,7 +233,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
for (const auto& xpub_pair : parent_xpub_cache) {
const CExtPubKey& xpub = xpub_pair.second;
CExtPubKey der;
- xpub.Derive(der, i);
+ BOOST_CHECK(xpub.Derive(der, i));
pubkeys.insert(der.pubkey);
}
int count_pks = 0;
@@ -266,7 +265,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
const CExtPubKey& xpub = xpub_pair.second;
pubkeys.insert(xpub.pubkey);
CExtPubKey der;
- xpub.Derive(der, i);
+ BOOST_CHECK(xpub.Derive(der, i));
pubkeys.insert(der.pubkey);
}
int count_pks = 0;
@@ -303,7 +302,6 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
// For each of the produced scripts, verify solvability, and when possible, try to sign a transaction spending it.
for (size_t n = 0; n < spks.size(); ++n) {
BOOST_CHECK_EQUAL(ref[n], HexStr(spks[n]));
- BOOST_CHECK_EQUAL(IsSolvable(Merge(key_provider, script_provider), spks[n]), (flags & UNSOLVABLE) == 0);
if (flags & SIGNABLE) {
CMutableTransaction spend;
@@ -314,7 +312,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
txdata.Init(spend, std::move(utxos), /*force=*/true);
MutableTransactionSignatureCreator creator{spend, 0, CAmount{0}, &txdata, SIGHASH_DEFAULT};
SignatureData sigdata;
- BOOST_CHECK_MESSAGE(ProduceSignature(Merge(keys_priv, script_provider), creator, spks[n], sigdata), prv);
+ BOOST_CHECK_MESSAGE(ProduceSignature(FlatSigningProvider{keys_priv}.Merge(FlatSigningProvider{script_provider}), creator, spks[n], sigdata), prv);
}
/* Infer a descriptor from the generated script, and verify its solvability and that it roundtrips. */
@@ -325,7 +323,7 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
BOOST_CHECK(inferred->Expand(0, provider_inferred, spks_inferred, provider_inferred));
BOOST_CHECK_EQUAL(spks_inferred.size(), 1U);
BOOST_CHECK(spks_inferred[0] == spks[n]);
- BOOST_CHECK_EQUAL(IsSolvable(provider_inferred, spks_inferred[0]), !(flags & UNSOLVABLE));
+ BOOST_CHECK_EQUAL(InferDescriptor(spks_inferred[0], provider_inferred)->IsSolvable(), !(flags & UNSOLVABLE));
BOOST_CHECK(GetKeyOriginData(provider_inferred, flags) == GetKeyOriginData(script_provider, flags));
}
@@ -342,29 +340,29 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
BOOST_CHECK_MESSAGE(left_paths.empty(), "Not all expected key paths found: " + prv);
}
-void Check(const std::string& prv, const std::string& pub, const std::string& norm_prv, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
+void Check(const std::string& prv, const std::string& pub, const std::string& norm_pub, int flags, const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type, const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY)
{
bool found_apostrophes_in_prv = false;
bool found_apostrophes_in_pub = false;
// Do not replace apostrophes with 'h' in prv and pub
- DoCheck(prv, pub, norm_prv, norm_pub, flags, scripts, type, paths);
+ DoCheck(prv, pub, norm_pub, flags, scripts, type, paths);
// Replace apostrophes with 'h' in prv but not in pub, if apostrophes are found in prv
if (prv.find('\'') != std::string::npos) {
found_apostrophes_in_prv = true;
- DoCheck(prv, pub, norm_prv, norm_pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */false);
+ DoCheck(prv, pub, norm_pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */false);
}
// Replace apostrophes with 'h' in pub but not in prv, if apostrophes are found in pub
if (pub.find('\'') != std::string::npos) {
found_apostrophes_in_pub = true;
- DoCheck(prv, pub, norm_prv, norm_pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */false, /*replace_apostrophe_with_h_in_pub = */true);
+ DoCheck(prv, pub, norm_pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */false, /*replace_apostrophe_with_h_in_pub = */true);
}
// Replace apostrophes with 'h' both in prv and in pub, if apostrophes are found in both
if (found_apostrophes_in_prv && found_apostrophes_in_pub) {
- DoCheck(prv, pub, norm_prv, norm_pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */true);
+ DoCheck(prv, pub, norm_pub, flags, scripts, type, paths, /* replace_apostrophe_with_h_in_prv = */true, /*replace_apostrophe_with_h_in_pub = */true);
}
}
@@ -375,60 +373,61 @@ BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(descriptor_test)
{
// Basic single-key compressed
- Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, std::nullopt);
- Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, std::nullopt);
- Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, OutputType::LEGACY, {{1,0x80000002UL,3,0x80000004UL}});
- Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}}, OutputType::BECH32);
- Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, OutputType::P2SH_SEGWIT);
- Check("tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE | XONLY_KEYS, {{"512077aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11"}}, OutputType::BECH32M);
+ Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, std::nullopt);
+ Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, std::nullopt);
+ Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, OutputType::LEGACY, {{1,0x80000002UL,3,0x80000004UL}});
+ Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}}, OutputType::BECH32);
+ Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, OutputType::P2SH_SEGWIT);
+ Check("tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE | XONLY_KEYS, {{"512077aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11"}}, OutputType::BECH32M);
CheckUnparsable("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY2))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5))", "wpkh(): Pubkey '03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5' is invalid"); // Invalid pubkey
CheckUnparsable("pkh(deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh(deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh(): Key origin start '[ character expected but not found, got 'd' instead"); // Missing start bracket in key origin
CheckUnparsable("pkh([deadbeef]/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef]/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh(): Multiple ']' characters found for a single pubkey"); // Multiple end brackets in key origin
// Basic single-key uncompressed
- Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)",SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, std::nullopt);
- Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, std::nullopt);
- Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, OutputType::LEGACY);
+ Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)",SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, std::nullopt);
+ Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, std::nullopt);
+ Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, OutputType::LEGACY);
CheckUnparsable("wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "wpkh(): Uncompressed keys are not allowed"); // No uncompressed keys in witness
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
// Some unconventional single-key constructions
- Check("sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}}, OutputType::LEGACY);
- Check("sh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}}, OutputType::LEGACY);
- Check("wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"00202e271faa2325c199d25d22e1ead982e45b64eeb4f31e73dbdf41bd4b5fec23fa"}}, OutputType::BECH32);
- Check("wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"0020338e023079b91c58571b20e602d7805fb808c22473cbc391a41b1bd3a192e75b"}}, OutputType::BECH32);
- Check("sh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "sh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a91472d0c5a3bfad8c3e7bd5303a72b94240e80b6f1787"}}, OutputType::P2SH_SEGWIT);
- Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}}, OutputType::P2SH_SEGWIT);
- Check("tr(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5,{pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5),{pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1),pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5)}})", "tr(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5,{pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5),{pk(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd),pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5)}})", "tr(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5,{pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5),{pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1),pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5)}})", "tr(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5,{pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5),{pk(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd),pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5)}})", XONLY_KEYS | SIGNABLE | MISSING_PRIVKEYS, {{"51201497ae16f30dacb88523ed9301bff17773b609e8a90518a3f96ea328a47d1500"}}, OutputType::BECH32M);
+ 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);
+ Check("wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"00202e271faa2325c199d25d22e1ead982e45b64eeb4f31e73dbdf41bd4b5fec23fa"}}, OutputType::BECH32);
+ Check("wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"0020338e023079b91c58571b20e602d7805fb808c22473cbc391a41b1bd3a192e75b"}}, OutputType::BECH32);
+ Check("sh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a91472d0c5a3bfad8c3e7bd5303a72b94240e80b6f1787"}}, OutputType::P2SH_SEGWIT);
+ Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}}, OutputType::P2SH_SEGWIT);
+ Check("tr(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5,{pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5),{pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1),pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5)}})", "tr(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5,{pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5),{pk(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd),pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5)}})", "tr(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5,{pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5),{pk(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd),pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5)}})", XONLY_KEYS | SIGNABLE | MISSING_PRIVKEYS, {{"51201497ae16f30dacb88523ed9301bff17773b609e8a90518a3f96ea328a47d1500"}}, OutputType::BECH32M);
// Versions with BIP32 derivations
- Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, std::nullopt);
- Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", "pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, std::nullopt, {{0}});
- Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([bd16bee5/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0)", "pkh([bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{0xFFFFFFFFUL,0}});
- Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", "wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, OutputType::BECH32, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
- Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED | DERIVE_HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, OutputType::P2SH_SEGWIT, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
- Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", "combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, std::nullopt, {{0}, {1}});
- Check("tr(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/0/*,pk(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/1/*))", "tr(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*,pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*))", "tr(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/0/*,pk(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/1/*))", "tr(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*,pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*))", XONLY_KEYS | RANGE, {{"512078bc707124daa551b65af74de2ec128b7525e10f374dc67b64e00ce0ab8b3e12"}, {"512001f0a02a17808c20134b78faab80ef93ffba82261ccef0a2314f5d62b6438f11"}, {"512021024954fcec88237a9386fce80ef2ced5f1e91b422b26c59ccfc174c8d1ad25"}}, OutputType::BECH32M, {{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}});
+ Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, std::nullopt);
+ Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, std::nullopt, {{0}});
+ Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{0xFFFFFFFFUL,0}});
+
+ Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, OutputType::BECH32, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
+ Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED | DERIVE_HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, OutputType::P2SH_SEGWIT, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
+ Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, std::nullopt, {{0}, {1}});
+ Check("tr(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/0/*,pk(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/1/*))", "tr(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*,pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*))", "tr(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*,pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*))", XONLY_KEYS | RANGE, {{"512078bc707124daa551b65af74de2ec128b7525e10f374dc67b64e00ce0ab8b3e12"}, {"512001f0a02a17808c20134b78faab80ef93ffba82261ccef0a2314f5d62b6438f11"}, {"512021024954fcec88237a9386fce80ef2ced5f1e91b422b26c59ccfc174c8d1ad25"}}, OutputType::BECH32M, {{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}});
// Mixed xpubs and const pubkeys
- Check("wsh(multi(1,xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/0,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))","wsh(multi(1,xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/0,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))","wsh(multi(1,xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/0,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))","wsh(multi(1,xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/0,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", MIXED_PUBKEYS, {{"0020cb155486048b23a6da976d4c6fe071a2dbc8a7b57aaf225b8955f2e2a27b5f00"}},OutputType::BECH32,{{0},{}});
+ Check("wsh(multi(1,xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/0,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))","wsh(multi(1,xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/0,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))","wsh(multi(1,xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/0,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", MIXED_PUBKEYS, {{"0020cb155486048b23a6da976d4c6fe071a2dbc8a7b57aaf225b8955f2e2a27b5f00"}},OutputType::BECH32,{{0},{}});
// Mixed range xpubs and const pubkeys
- Check("multi(1,xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)","multi(1,xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)","multi(1,xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)","multi(1,xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", RANGE | MIXED_PUBKEYS, {{"512102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e0762103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd52ae"},{"5121032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ec2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd52ae"},{"5121035d30b6c66dc1e036c45369da8287518cf7e0d6ed1e2b905171c605708f14ca032103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd52ae"}}, std::nullopt,{{2},{1},{0},{}});
+ Check("multi(1,xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)","multi(1,xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)","multi(1,xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", RANGE | MIXED_PUBKEYS, {{"512102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e0762103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd52ae"},{"5121032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ec2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd52ae"},{"5121035d30b6c66dc1e036c45369da8287518cf7e0d6ed1e2b905171c605708f14ca032103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd52ae"}}, std::nullopt,{{2},{1},{0},{}});
CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo(): Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long key fingerprint
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)", "pkh(): Key path value 2147483648 is out of range"); // BIP 32 path element overflow
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/1aa)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1aa)", "pkh(): Key path value '1aa' is not a valid uint32"); // Path is not valid uint
- Check("pkh([01234567/10/20]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh([01234567/10/20]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([01234567/10/20/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0)", "pkh([01234567/10/20/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{10, 20, 0xFFFFFFFFUL, 0}});
+ Check("pkh([01234567/10/20]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh([01234567/10/20]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([01234567/10/20/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{10, 20, 0xFFFFFFFFUL, 0}});
// Multisig constructions
- Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
- Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
- Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
- Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", "sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, std::nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
- Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647']xprv9vHkqa6XAPwKqSKSEJMcAB3yoCZhaSVsGZbSkFY5L3Lfjjk8sjZucbsbvEw5o3QrSA69nPfZDCgFnNnLhQ2ohpZuwummndnPasDw2Qr6dC2/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE | DERIVE_HARDENED, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, OutputType::BECH32, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
- Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", "sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}, OutputType::P2SH_SEGWIT);
- Check("tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,pk(KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pk(669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))", "tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,pk(KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pk(669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))", SIGNABLE | XONLY_KEYS, {{"512017cf18db381d836d8923b1bdb246cfcd818da1a9f0e6e7907f187f0b2f937754"}}, OutputType::BECH32M);
+ Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
+ Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
+ Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
+ Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, std::nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
+ Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE | DERIVE_HARDENED, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, OutputType::BECH32, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
+ Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", "sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}, OutputType::P2SH_SEGWIT);
+ Check("tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,pk(KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pk(669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pk(669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))", SIGNABLE | XONLY_KEYS, {{"512017cf18db381d836d8923b1bdb246cfcd818da1a9f0e6e7907f187f0b2f937754"}}, OutputType::BECH32M);
CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))", "P2SH script is too large, 547 bytes is larger than 520 bytes"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
CheckUnparsable("wsh(multi(2,[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa][aaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multi: Multiple ']' characters found for a single pubkey"); // Double key origin descriptor
CheckUnparsable("wsh(multi(2,[aaaagaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaagaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multi: Fingerprint 'aaagaaaa' is not hex"); // Non hex fingerprint
@@ -440,8 +439,8 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
CheckUnparsable("multi(3,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(3,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Multisig threshold cannot be larger than the number of keys; threshold is 3 but only 2 keys specified"); // Threshold larger than number of keys
CheckUnparsable("multi(3,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f)", "multi(3,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8)", "Cannot have 4 pubkeys in bare multisig; only at most 3 pubkeys"); // Threshold larger than number of keys
CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "P2SH script is too large, 581 bytes is larger than 520 bytes"); // Cannot have more than 15 keys in a P2SH multisig, or we exceed maximum push size
- Check("wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9,KzRedjSwMggebB3VufhbzpYJnvHfHe9kPJSjCU5QpJdAW3NSZxYS,Kyjtp5858xL7JfeV4PNRCKy2t6XvgqNNepArGY9F9F1SSPqNEMs3,L2D4RLHPiHBidkHS8ftx11jJk1hGFELvxh8LoxNQheaGT58dKenW,KyLPZdwY4td98bKkXqEXTEBX3vwEYTQo1yyLjX2jKXA63GBpmSjv))","wsh(multi(20,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,02bc2feaa536991d269aae46abb8f3772a5b3ad592314945e51543e7da84c4af6e,0318bf32e5217c1eb771a6d5ce1cd39395dff7ff665704f175c9a5451d95a2f2ca,02c681a6243f16208c2004bb81f5a8a67edfdd3e3711534eadeec3dcf0b010c759,0249fdd6b69768b8d84b4893f8ff84b36835c50183de20fcae8f366a45290d01fd))", "wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9,KzRedjSwMggebB3VufhbzpYJnvHfHe9kPJSjCU5QpJdAW3NSZxYS,Kyjtp5858xL7JfeV4PNRCKy2t6XvgqNNepArGY9F9F1SSPqNEMs3,L2D4RLHPiHBidkHS8ftx11jJk1hGFELvxh8LoxNQheaGT58dKenW,KyLPZdwY4td98bKkXqEXTEBX3vwEYTQo1yyLjX2jKXA63GBpmSjv))","wsh(multi(20,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,02bc2feaa536991d269aae46abb8f3772a5b3ad592314945e51543e7da84c4af6e,0318bf32e5217c1eb771a6d5ce1cd39395dff7ff665704f175c9a5451d95a2f2ca,02c681a6243f16208c2004bb81f5a8a67edfdd3e3711534eadeec3dcf0b010c759,0249fdd6b69768b8d84b4893f8ff84b36835c50183de20fcae8f366a45290d01fd))", SIGNABLE, {{"0020376bd8344b8b6ebe504ff85ef743eaa1aa9272178223bcb6887e9378efb341ac"}}, OutputType::BECH32); // In P2WSH we can have up to 20 keys
-Check("sh(wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9,KzRedjSwMggebB3VufhbzpYJnvHfHe9kPJSjCU5QpJdAW3NSZxYS,Kyjtp5858xL7JfeV4PNRCKy2t6XvgqNNepArGY9F9F1SSPqNEMs3,L2D4RLHPiHBidkHS8ftx11jJk1hGFELvxh8LoxNQheaGT58dKenW,KyLPZdwY4td98bKkXqEXTEBX3vwEYTQo1yyLjX2jKXA63GBpmSjv)))","sh(wsh(multi(20,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,02bc2feaa536991d269aae46abb8f3772a5b3ad592314945e51543e7da84c4af6e,0318bf32e5217c1eb771a6d5ce1cd39395dff7ff665704f175c9a5451d95a2f2ca,02c681a6243f16208c2004bb81f5a8a67edfdd3e3711534eadeec3dcf0b010c759,0249fdd6b69768b8d84b4893f8ff84b36835c50183de20fcae8f366a45290d01fd)))", "sh(wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9,KzRedjSwMggebB3VufhbzpYJnvHfHe9kPJSjCU5QpJdAW3NSZxYS,Kyjtp5858xL7JfeV4PNRCKy2t6XvgqNNepArGY9F9F1SSPqNEMs3,L2D4RLHPiHBidkHS8ftx11jJk1hGFELvxh8LoxNQheaGT58dKenW,KyLPZdwY4td98bKkXqEXTEBX3vwEYTQo1yyLjX2jKXA63GBpmSjv)))","sh(wsh(multi(20,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,02bc2feaa536991d269aae46abb8f3772a5b3ad592314945e51543e7da84c4af6e,0318bf32e5217c1eb771a6d5ce1cd39395dff7ff665704f175c9a5451d95a2f2ca,02c681a6243f16208c2004bb81f5a8a67edfdd3e3711534eadeec3dcf0b010c759,0249fdd6b69768b8d84b4893f8ff84b36835c50183de20fcae8f366a45290d01fd)))", SIGNABLE, {{"a914c2c9c510e9d7f92fd6131e94803a8d34a8ef675e87"}}, OutputType::P2SH_SEGWIT); // Even if it's wrapped into P2SH
+ Check("wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9,KzRedjSwMggebB3VufhbzpYJnvHfHe9kPJSjCU5QpJdAW3NSZxYS,Kyjtp5858xL7JfeV4PNRCKy2t6XvgqNNepArGY9F9F1SSPqNEMs3,L2D4RLHPiHBidkHS8ftx11jJk1hGFELvxh8LoxNQheaGT58dKenW,KyLPZdwY4td98bKkXqEXTEBX3vwEYTQo1yyLjX2jKXA63GBpmSjv))","wsh(multi(20,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,02bc2feaa536991d269aae46abb8f3772a5b3ad592314945e51543e7da84c4af6e,0318bf32e5217c1eb771a6d5ce1cd39395dff7ff665704f175c9a5451d95a2f2ca,02c681a6243f16208c2004bb81f5a8a67edfdd3e3711534eadeec3dcf0b010c759,0249fdd6b69768b8d84b4893f8ff84b36835c50183de20fcae8f366a45290d01fd))", "wsh(multi(20,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,02bc2feaa536991d269aae46abb8f3772a5b3ad592314945e51543e7da84c4af6e,0318bf32e5217c1eb771a6d5ce1cd39395dff7ff665704f175c9a5451d95a2f2ca,02c681a6243f16208c2004bb81f5a8a67edfdd3e3711534eadeec3dcf0b010c759,0249fdd6b69768b8d84b4893f8ff84b36835c50183de20fcae8f366a45290d01fd))", SIGNABLE, {{"0020376bd8344b8b6ebe504ff85ef743eaa1aa9272178223bcb6887e9378efb341ac"}}, OutputType::BECH32); // In P2WSH we can have up to 20 keys
+ Check("sh(wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9,KzRedjSwMggebB3VufhbzpYJnvHfHe9kPJSjCU5QpJdAW3NSZxYS,Kyjtp5858xL7JfeV4PNRCKy2t6XvgqNNepArGY9F9F1SSPqNEMs3,L2D4RLHPiHBidkHS8ftx11jJk1hGFELvxh8LoxNQheaGT58dKenW,KyLPZdwY4td98bKkXqEXTEBX3vwEYTQo1yyLjX2jKXA63GBpmSjv)))","sh(wsh(multi(20,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,02bc2feaa536991d269aae46abb8f3772a5b3ad592314945e51543e7da84c4af6e,0318bf32e5217c1eb771a6d5ce1cd39395dff7ff665704f175c9a5451d95a2f2ca,02c681a6243f16208c2004bb81f5a8a67edfdd3e3711534eadeec3dcf0b010c759,0249fdd6b69768b8d84b4893f8ff84b36835c50183de20fcae8f366a45290d01fd)))", "sh(wsh(multi(20,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232,02bc2feaa536991d269aae46abb8f3772a5b3ad592314945e51543e7da84c4af6e,0318bf32e5217c1eb771a6d5ce1cd39395dff7ff665704f175c9a5451d95a2f2ca,02c681a6243f16208c2004bb81f5a8a67edfdd3e3711534eadeec3dcf0b010c759,0249fdd6b69768b8d84b4893f8ff84b36835c50183de20fcae8f366a45290d01fd)))", SIGNABLE, {{"a914c2c9c510e9d7f92fd6131e94803a8d34a8ef675e87"}}, OutputType::P2SH_SEGWIT); // Even if it's wrapped into P2SH
// Check for invalid nesting of structures
CheckUnparsable("sh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "A function is needed within P2SH"); // P2SH needs a script, not a key
CheckUnparsable("sh(combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "Can only have combo() at top level"); // Old must be top level
@@ -452,8 +451,8 @@ Check("sh(wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGN
CheckUnparsable("wsh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "Can only have wsh() at top level or inside sh()"); // Cannot embed P2WSH inside P2WSH
// Checksums
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#", "Expected 8 character checksum, not 0 characters"); // Empty checksum
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq", "Expected 8 character checksum, not 9 characters"); // Too long checksum
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5", "Expected 8 character checksum, not 7 characters"); // Too short checksum
@@ -466,6 +465,29 @@ Check("sh(wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGN
CheckUnparsable("", "raw(asdf)", "Raw script is not hex"); // Invalid script
CheckUnparsable("", "raw(Ü)#00000000", "Invalid characters in payload"); // Invalid chars
+ Check(
+ "rawtr(xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/86'/1'/0'/1/*)#a5gn3t7k",
+ "rawtr(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/86'/1'/0'/1/*)#4ur3xhft",
+ "rawtr([5a61ff8e/86'/1'/0']xpub6DtZpc9PRL2B6pwoNGysmHAaBofDmWv5S6KQEKKGPKhf5fV62ywDtSziSApYVK3JnYY5KUSgiCwiXW5wtd8z7LNBxT9Mu5sEro8itdGfTeA/1/*)#llheyd9x",
+ RANGE | HARDENED | XONLY_KEYS,
+ {{"51205172af752f057d543ce8e4a6f8dcf15548ec6be44041bfa93b72e191cfc8c1ee"}, {"51201b66f20b86f700c945ecb9ad9b0ad1662b73084e2bfea48bee02126350b8a5b1"}, {"512063e70f66d815218abcc2306aa930aaca07c5cde73b75127eb27b5e8c16b58a25"}},
+ OutputType::BECH32M,
+ {{0x80000056, 0x80000001, 0x80000000, 1, 0}, {0x80000056, 0x80000001, 0x80000000, 1, 1}, {0x80000056, 0x80000001, 0x80000000, 1, 2}});
+
+
+ Check(
+ "rawtr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)",
+ "rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)",
+ "rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)",
+ SIGNABLE | XONLY_KEYS,
+ {{"5120a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd"}},
+ OutputType::BECH32M);
+
+ CheckUnparsable(
+ "",
+ "rawtr(xpub68FQ9imX6mCWacw6eNRjaa8q8ynnHmUd5i7MVR51ZMPP5JycyfVHSLQVFPHMYiTybWJnSBL2tCBpy6aJTR2DYrshWYfwAxs8SosGXd66d8/*, xpub69Mvq3QMipdvnd9hAyeTnT5jrkcBuLErV212nsGf3qr7JPWysc9HnNhCsazdzj1etSx28hPSE8D7DnceFbNdw4Kg8SyRfjE2HFLv1P8TSGc/*)",
+ "rawtr(): only one key expected.");
+
// A 2of4 but using a direct push rather than OP_2
CScript nonminimalmultisig;
CKey keys[4];
@@ -486,6 +508,29 @@ Check("sh(wsh(multi(20,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGN
}
nonminimalmultisig << std::vector<unsigned char>{4} << OP_CHECKMULTISIG;
CheckInferRaw(nonminimalmultisig);
+
+ // Miniscript tests
+
+ // 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");
+ 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("", "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");
+ // 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
+ CheckUnparsable("wsh(and_v(vc:andor(v:pk_k(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),pk_k(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn),and_v(v:older(1),pk_k(L4o2kDvXXDRH2VS9uBnouScLduWt4dZnM25se7kvEjJeQ285en2A))),after(10)))", "wsh(and_v(vc:andor(v:pk_k(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),pk_k(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0),and_v(v:older(1),pk_k(02aa27e5eb2c185e87cd1dbc3e0efc9cb1175235e0259df1713424941c3cb40402))),after(10)))", "v:pk_k(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204) is invalid");
+ // Insane subs
+ CheckUnparsable("wsh(or_i(older(1),pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd)))", "wsh(or_i(older(1),pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)))", "or_i(older(1),pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)) is not sane: witnesses without signature exist");
+ CheckUnparsable("wsh(or_b(sha256(cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),s:pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)))", "wsh(or_b(sha256(cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),s:pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)))", "or_b(sha256(cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),s:pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)) is not sane: malleable witnesses exist");
+ CheckUnparsable("wsh(and_b(and_b(older(1),a:older(100000000)),s:pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd)))", "wsh(and_b(and_b(older(1),a:older(100000000)),s:pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)))", "and_b(older(1),a:older(100000000)) is not sane: contains mixes of timelocks expressed in blocks and seconds");
+ CheckUnparsable("wsh(and_b(or_b(pkh(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),s:pk(Kx9HCDjGiwFcgVNhTrS5z5NeZdD6veeam61eDxLDCkGWujvL4Gnn)),s:pk(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd)))", "wsh(and_b(or_b(pkh(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),s:pk(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0)),s:pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)))", "and_b(or_b(pkh(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),s:pk(032707170c71d8f75e4ca4e3fce870b9409dcaf12b051d3bcadff74747fa7619c0)),s:pk(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204)) is not sane: contains duplicate public keys");
+ // Valid with extended keys.
+ Check("wsh(and_v(v:ripemd160(095ff41131e5946f3c85f79e44adbcf8e27e080e),multi(1,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)))", "wsh(and_v(v:ripemd160(095ff41131e5946f3c85f79e44adbcf8e27e080e),multi(1,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)))", "wsh(and_v(v:ripemd160(095ff41131e5946f3c85f79e44adbcf8e27e080e),multi(1,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)))", UNSOLVABLE, {{"0020acf425291b98a1d7e0d4690139442abc289175be32ef1f75945e339924246d73"}}, OutputType::BECH32, {{},{0}});
+ // Valid under sh(wsh()) and with a mix of xpubs and raw keys
+ Check("sh(wsh(thresh(1,pkh(L4gM1FBdyHNpkzsFh9ipnofLhpZRp2mwobpeULy1a6dBTvw8Ywtd),a:and_n(multi(1,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0),n:older(2)))))", "sh(wsh(thresh(1,pkh(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),a:and_n(multi(1,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0),n:older(2)))))", "sh(wsh(thresh(1,pkh(03cdabb7f2dce7bfbd8a0b9570c6fd1e712e5d64045e9d6b517b3d5072251dc204),a:and_n(multi(1,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0),n:older(2)))))", UNSOLVABLE | MIXED_PUBKEYS, {{"a914767e9119ff3b3ac0cb6dcfe21de1842ccf85f1c487"}}, OutputType::P2SH_SEGWIT, {{},{0}});
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp
index d54d6b6471..605faa08e4 100644
--- a/src/test/flatfile_tests.cpp
+++ b/src/test/flatfile_tests.cpp
@@ -41,26 +41,26 @@ BOOST_AUTO_TEST_CASE(flatfile_open)
// Write first line to file.
{
- CAutoFile file(seq.Open(FlatFilePos(0, pos1)), SER_DISK, CLIENT_VERSION);
+ AutoFile file{seq.Open(FlatFilePos(0, pos1))};
file << LIMITED_STRING(line1, 256);
}
// Attempt to append to file opened in read-only mode.
{
- CAutoFile file(seq.Open(FlatFilePos(0, pos2), true), SER_DISK, CLIENT_VERSION);
+ AutoFile file{seq.Open(FlatFilePos(0, pos2), true)};
BOOST_CHECK_THROW(file << LIMITED_STRING(line2, 256), std::ios_base::failure);
}
// Append second line to file.
{
- CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION);
+ AutoFile file{seq.Open(FlatFilePos(0, pos2))};
file << LIMITED_STRING(line2, 256);
}
// Read text from file in read-only mode.
{
std::string text;
- CAutoFile file(seq.Open(FlatFilePos(0, pos1), true), SER_DISK, CLIENT_VERSION);
+ AutoFile file{seq.Open(FlatFilePos(0, pos1), true)};
file >> LIMITED_STRING(text, 256);
BOOST_CHECK_EQUAL(text, line1);
@@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(flatfile_open)
// Read text from file with position offset.
{
std::string text;
- CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION);
+ AutoFile file{seq.Open(FlatFilePos(0, pos2))};
file >> LIMITED_STRING(text, 256);
BOOST_CHECK_EQUAL(text, line2);
@@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(flatfile_open)
// Ensure another file in the sequence has no data.
{
std::string text;
- CAutoFile file(seq.Open(FlatFilePos(1, pos2)), SER_DISK, CLIENT_VERSION);
+ AutoFile file{seq.Open(FlatFilePos(1, pos2))};
BOOST_CHECK_THROW(file >> LIMITED_STRING(text, 256), std::ios_base::failure);
}
}
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
index af7a282781..7668940cbc 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -113,11 +113,11 @@ void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
for (size_t j = 0; j < num_addresses; ++j) {
const auto addr = CAddress{CService{RandAddr(fuzzed_data_provider, fast_random_context), 8333}, NODE_NETWORK};
- const auto time_penalty = fast_random_context.randrange(100000001);
+ const std::chrono::seconds time_penalty{fast_random_context.randrange(100000001)};
addrman.Add({addr}, source, time_penalty);
if (n > 0 && addrman.size() % n == 0) {
- addrman.Good(addr, GetTime());
+ addrman.Good(addr, Now<NodeSeconds>());
}
// Add 10% of the addresses from more than one source.
@@ -161,7 +161,7 @@ public:
CSipHasher hasher(0, 0);
auto addr_key = a.GetKey();
auto source_key = a.source.GetAddrBytes();
- hasher.Write(a.nLastSuccess);
+ hasher.Write(TicksSinceEpoch<std::chrono::seconds>(a.m_last_success));
hasher.Write(a.nAttempts);
hasher.Write(a.nRefCount);
hasher.Write(a.fInTried);
@@ -175,8 +175,8 @@ public:
};
auto addrinfo_eq = [](const AddrInfo& lhs, const AddrInfo& rhs) {
- return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.nLastSuccess, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
- std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.nLastSuccess, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
+ return std::tie(static_cast<const CService&>(lhs), lhs.source, lhs.m_last_success, lhs.nAttempts, lhs.nRefCount, lhs.fInTried) ==
+ std::tie(static_cast<const CService&>(rhs), rhs.source, rhs.m_last_success, rhs.nAttempts, rhs.nRefCount, rhs.fInTried);
};
using Addresses = std::unordered_set<AddrInfo, decltype(addrinfo_hasher), decltype(addrinfo_eq)>;
@@ -269,25 +269,25 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
}
const std::optional<CNetAddr> opt_net_addr = ConsumeDeserializable<CNetAddr>(fuzzed_data_provider);
if (opt_net_addr) {
- addr_man.Add(addresses, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 100000000));
+ addr_man.Add(addresses, *opt_net_addr, std::chrono::seconds{ConsumeTime(fuzzed_data_provider, 0, 100000000)});
}
},
[&] {
const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (opt_service) {
- addr_man.Good(*opt_service, ConsumeTime(fuzzed_data_provider));
+ addr_man.Good(*opt_service, NodeSeconds{std::chrono::seconds{ConsumeTime(fuzzed_data_provider)}});
}
},
[&] {
const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (opt_service) {
- addr_man.Attempt(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider));
+ addr_man.Attempt(*opt_service, fuzzed_data_provider.ConsumeBool(), NodeSeconds{std::chrono::seconds{ConsumeTime(fuzzed_data_provider)}});
}
},
[&] {
const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (opt_service) {
- addr_man.Connected(*opt_service, ConsumeTime(fuzzed_data_provider));
+ addr_man.Connected(*opt_service, NodeSeconds{std::chrono::seconds{ConsumeTime(fuzzed_data_provider)}});
}
},
[&] {
diff --git a/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp
index 3b410930ed..1a8957d090 100644
--- a/src/test/fuzz/autofile.cpp
+++ b/src/test/fuzz/autofile.cpp
@@ -18,7 +18,7 @@ FUZZ_TARGET(autofile)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
- CAutoFile auto_file = fuzzed_auto_file_provider.open();
+ AutoFile auto_file{fuzzed_auto_file_provider.open()};
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
CallOneOf(
fuzzed_data_provider,
@@ -53,8 +53,6 @@ FUZZ_TARGET(autofile)
});
}
(void)auto_file.Get();
- (void)auto_file.GetType();
- (void)auto_file.GetVersion();
(void)auto_file.IsNull();
if (fuzzed_data_provider.ConsumeBool()) {
FILE* f = auto_file.release();
diff --git a/src/test/fuzz/bitdeque.cpp b/src/test/fuzz/bitdeque.cpp
new file mode 100644
index 0000000000..634a3de346
--- /dev/null
+++ b/src/test/fuzz/bitdeque.cpp
@@ -0,0 +1,541 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <random.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/util.h>
+#include <util/bitdeque.h>
+
+#include <deque>
+#include <vector>
+
+namespace {
+
+constexpr int LEN_BITS = 16;
+constexpr int RANDDATA_BITS = 20;
+
+using bitdeque_type = bitdeque<128>;
+
+//! Deterministic random vector of bools, for begin/end insertions to draw from.
+std::vector<bool> RANDDATA;
+
+void InitRandData()
+{
+ FastRandomContext ctx(true);
+ RANDDATA.clear();
+ for (size_t i = 0; i < (1U << RANDDATA_BITS) + (1U << LEN_BITS); ++i) {
+ RANDDATA.push_back(ctx.randbool());
+ }
+}
+
+} // namespace
+
+FUZZ_TARGET_INIT(bitdeque, InitRandData)
+{
+ FuzzedDataProvider provider(buffer.data(), buffer.size());
+ FastRandomContext ctx(true);
+
+ size_t maxlen = (1U << provider.ConsumeIntegralInRange<size_t>(0, LEN_BITS)) - 1;
+ size_t limitlen = 4 * maxlen;
+
+ std::deque<bool> deq;
+ bitdeque_type bitdeq;
+
+ const auto& cdeq = deq;
+ const auto& cbitdeq = bitdeq;
+
+ size_t initlen = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ while (initlen) {
+ bool val = ctx.randbool();
+ deq.push_back(val);
+ bitdeq.push_back(val);
+ --initlen;
+ }
+
+ LIMITED_WHILE(provider.remaining_bytes() > 0, 900)
+ {
+ {
+ assert(deq.size() == bitdeq.size());
+ auto it = deq.begin();
+ auto bitit = bitdeq.begin();
+ auto itend = deq.end();
+ while (it != itend) {
+ assert(*it == *bitit);
+ ++it;
+ ++bitit;
+ }
+ }
+
+ CallOneOf(provider,
+ [&] {
+ // constructor()
+ deq = std::deque<bool>{};
+ bitdeq = bitdeque_type{};
+ },
+ [&] {
+ // clear()
+ deq.clear();
+ bitdeq.clear();
+ },
+ [&] {
+ // resize()
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ deq.resize(count);
+ bitdeq.resize(count);
+ },
+ [&] {
+ // assign(count, val)
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ bool val = ctx.randbool();
+ deq.assign(count, val);
+ bitdeq.assign(count, val);
+ },
+ [&] {
+ // constructor(count, val)
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ bool val = ctx.randbool();
+ deq = std::deque<bool>(count, val);
+ bitdeq = bitdeque_type(count, val);
+ },
+ [&] {
+ // constructor(count)
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ deq = std::deque<bool>(count);
+ bitdeq = bitdeque_type(count);
+ },
+ [&] {
+ // construct(begin, end)
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS);
+ auto rand_end = rand_begin + count;
+ deq = std::deque<bool>(rand_begin, rand_end);
+ bitdeq = bitdeque_type(rand_begin, rand_end);
+ },
+ [&] {
+ // assign(begin, end)
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS);
+ auto rand_end = rand_begin + count;
+ deq.assign(rand_begin, rand_end);
+ bitdeq.assign(rand_begin, rand_end);
+ },
+ [&] {
+ // construct(initializer_list)
+ std::initializer_list<bool> ilist{ctx.randbool(), ctx.randbool(), ctx.randbool(), ctx.randbool(), ctx.randbool()};
+ deq = std::deque<bool>(ilist);
+ bitdeq = bitdeque_type(ilist);
+ },
+ [&] {
+ // assign(initializer_list)
+ std::initializer_list<bool> ilist{ctx.randbool(), ctx.randbool(), ctx.randbool()};
+ deq.assign(ilist);
+ bitdeq.assign(ilist);
+ },
+ [&] {
+ // operator=(const&)
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ bool val = ctx.randbool();
+ const std::deque<bool> deq2(count, val);
+ deq = deq2;
+ const bitdeque_type bitdeq2(count, val);
+ bitdeq = bitdeq2;
+ },
+ [&] {
+ // operator=(&&)
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ bool val = ctx.randbool();
+ std::deque<bool> deq2(count, val);
+ deq = std::move(deq2);
+ bitdeque_type bitdeq2(count, val);
+ bitdeq = std::move(bitdeq2);
+ },
+ [&] {
+ // deque swap
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS);
+ auto rand_end = rand_begin + count;
+ std::deque<bool> deq2(rand_begin, rand_end);
+ bitdeque_type bitdeq2(rand_begin, rand_end);
+ using std::swap;
+ assert(deq.size() == bitdeq.size());
+ assert(deq2.size() == bitdeq2.size());
+ swap(deq, deq2);
+ swap(bitdeq, bitdeq2);
+ assert(deq.size() == bitdeq.size());
+ assert(deq2.size() == bitdeq2.size());
+ },
+ [&] {
+ // deque.swap
+ auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS);
+ auto rand_end = rand_begin + count;
+ std::deque<bool> deq2(rand_begin, rand_end);
+ bitdeque_type bitdeq2(rand_begin, rand_end);
+ assert(deq.size() == bitdeq.size());
+ assert(deq2.size() == bitdeq2.size());
+ deq.swap(deq2);
+ bitdeq.swap(bitdeq2);
+ assert(deq.size() == bitdeq.size());
+ assert(deq2.size() == bitdeq2.size());
+ },
+ [&] {
+ // operator=(initializer_list)
+ std::initializer_list<bool> ilist{ctx.randbool(), ctx.randbool(), ctx.randbool()};
+ deq = ilist;
+ bitdeq = ilist;
+ },
+ [&] {
+ // iterator arithmetic
+ auto pos1 = provider.ConsumeIntegralInRange<long>(0, cdeq.size());
+ auto pos2 = provider.ConsumeIntegralInRange<long>(0, cdeq.size());
+ auto it = deq.begin() + pos1;
+ auto bitit = bitdeq.begin() + pos1;
+ if ((size_t)pos1 != cdeq.size()) assert(*it == *bitit);
+ assert(it - deq.begin() == pos1);
+ assert(bitit - bitdeq.begin() == pos1);
+ if (provider.ConsumeBool()) {
+ it += pos2 - pos1;
+ bitit += pos2 - pos1;
+ } else {
+ it -= pos1 - pos2;
+ bitit -= pos1 - pos2;
+ }
+ if ((size_t)pos2 != cdeq.size()) assert(*it == *bitit);
+ assert(deq.end() - it == bitdeq.end() - bitit);
+ if (provider.ConsumeBool()) {
+ if ((size_t)pos2 != cdeq.size()) {
+ ++it;
+ ++bitit;
+ }
+ } else {
+ if (pos2 != 0) {
+ --it;
+ --bitit;
+ }
+ }
+ assert(deq.end() - it == bitdeq.end() - bitit);
+ },
+ [&] {
+ // begin() and end()
+ assert(deq.end() - deq.begin() == bitdeq.end() - bitdeq.begin());
+ },
+ [&] {
+ // begin() and end() (const)
+ assert(cdeq.end() - cdeq.begin() == cbitdeq.end() - cbitdeq.begin());
+ },
+ [&] {
+ // rbegin() and rend()
+ assert(deq.rend() - deq.rbegin() == bitdeq.rend() - bitdeq.rbegin());
+ },
+ [&] {
+ // rbegin() and rend() (const)
+ assert(cdeq.rend() - cdeq.rbegin() == cbitdeq.rend() - cbitdeq.rbegin());
+ },
+ [&] {
+ // cbegin() and cend()
+ assert(cdeq.cend() - cdeq.cbegin() == cbitdeq.cend() - cbitdeq.cbegin());
+ },
+ [&] {
+ // crbegin() and crend()
+ assert(cdeq.crend() - cdeq.crbegin() == cbitdeq.crend() - cbitdeq.crbegin());
+ },
+ [&] {
+ // size() and maxsize()
+ assert(cdeq.size() == cbitdeq.size());
+ assert(cbitdeq.size() <= cbitdeq.max_size());
+ },
+ [&] {
+ // empty
+ assert(cdeq.empty() == cbitdeq.empty());
+ },
+ [&] {
+ // at (in range) and flip
+ if (!cdeq.empty()) {
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1);
+ auto& ref = deq.at(pos);
+ auto bitref = bitdeq.at(pos);
+ assert(ref == bitref);
+ if (ctx.randbool()) {
+ ref = !ref;
+ bitref.flip();
+ }
+ }
+ },
+ [&] {
+ // at (maybe out of range) and bit assign
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() + maxlen);
+ bool newval = ctx.randbool();
+ bool throw_deq{false}, throw_bitdeq{false};
+ bool val_deq{false}, val_bitdeq{false};
+ try {
+ auto& ref = deq.at(pos);
+ val_deq = ref;
+ ref = newval;
+ } catch (const std::out_of_range&) {
+ throw_deq = true;
+ }
+ try {
+ auto ref = bitdeq.at(pos);
+ val_bitdeq = ref;
+ ref = newval;
+ } catch (const std::out_of_range&) {
+ throw_bitdeq = true;
+ }
+ assert(throw_deq == throw_bitdeq);
+ assert(throw_bitdeq == (pos >= cdeq.size()));
+ if (!throw_deq) assert(val_deq == val_bitdeq);
+ },
+ [&] {
+ // at (maybe out of range) (const)
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() + maxlen);
+ bool throw_deq{false}, throw_bitdeq{false};
+ bool val_deq{false}, val_bitdeq{false};
+ try {
+ auto& ref = cdeq.at(pos);
+ val_deq = ref;
+ } catch (const std::out_of_range&) {
+ throw_deq = true;
+ }
+ try {
+ auto ref = cbitdeq.at(pos);
+ val_bitdeq = ref;
+ } catch (const std::out_of_range&) {
+ throw_bitdeq = true;
+ }
+ assert(throw_deq == throw_bitdeq);
+ assert(throw_bitdeq == (pos >= cdeq.size()));
+ if (!throw_deq) assert(val_deq == val_bitdeq);
+ },
+ [&] {
+ // operator[]
+ if (!cdeq.empty()) {
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1);
+ assert(deq[pos] == bitdeq[pos]);
+ if (ctx.randbool()) {
+ deq[pos] = !deq[pos];
+ bitdeq[pos].flip();
+ }
+ }
+ },
+ [&] {
+ // operator[] const
+ if (!cdeq.empty()) {
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1);
+ assert(deq[pos] == bitdeq[pos]);
+ }
+ },
+ [&] {
+ // front()
+ if (!cdeq.empty()) {
+ auto& ref = deq.front();
+ auto bitref = bitdeq.front();
+ assert(ref == bitref);
+ if (ctx.randbool()) {
+ ref = !ref;
+ bitref = !bitref;
+ }
+ }
+ },
+ [&] {
+ // front() const
+ if (!cdeq.empty()) {
+ auto& ref = cdeq.front();
+ auto bitref = cbitdeq.front();
+ assert(ref == bitref);
+ }
+ },
+ [&] {
+ // back() and swap(bool, ref)
+ if (!cdeq.empty()) {
+ auto& ref = deq.back();
+ auto bitref = bitdeq.back();
+ assert(ref == bitref);
+ if (ctx.randbool()) {
+ ref = !ref;
+ bitref.flip();
+ }
+ }
+ },
+ [&] {
+ // back() const
+ if (!cdeq.empty()) {
+ const auto& cdeq = deq;
+ const auto& cbitdeq = bitdeq;
+ auto& ref = cdeq.back();
+ auto bitref = cbitdeq.back();
+ assert(ref == bitref);
+ }
+ },
+ [&] {
+ // push_back()
+ if (cdeq.size() < limitlen) {
+ bool val = ctx.randbool();
+ if (cdeq.empty()) {
+ deq.push_back(val);
+ bitdeq.push_back(val);
+ } else {
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1);
+ auto& ref = deq[pos];
+ auto bitref = bitdeq[pos];
+ assert(ref == bitref);
+ deq.push_back(val);
+ bitdeq.push_back(val);
+ assert(ref == bitref); // references are not invalidated
+ }
+ }
+ },
+ [&] {
+ // push_front()
+ if (cdeq.size() < limitlen) {
+ bool val = ctx.randbool();
+ if (cdeq.empty()) {
+ deq.push_front(val);
+ bitdeq.push_front(val);
+ } else {
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1);
+ auto& ref = deq[pos];
+ auto bitref = bitdeq[pos];
+ assert(ref == bitref);
+ deq.push_front(val);
+ bitdeq.push_front(val);
+ assert(ref == bitref); // references are not invalidated
+ }
+ }
+ },
+ [&] {
+ // pop_back()
+ if (!cdeq.empty()) {
+ if (cdeq.size() == 1) {
+ deq.pop_back();
+ bitdeq.pop_back();
+ } else {
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 2);
+ auto& ref = deq[pos];
+ auto bitref = bitdeq[pos];
+ assert(ref == bitref);
+ deq.pop_back();
+ bitdeq.pop_back();
+ assert(ref == bitref); // references to other elements are not invalidated
+ }
+ }
+ },
+ [&] {
+ // pop_front()
+ if (!cdeq.empty()) {
+ if (cdeq.size() == 1) {
+ deq.pop_front();
+ bitdeq.pop_front();
+ } else {
+ size_t pos = provider.ConsumeIntegralInRange<size_t>(1, cdeq.size() - 1);
+ auto& ref = deq[pos];
+ auto bitref = bitdeq[pos];
+ assert(ref == bitref);
+ deq.pop_front();
+ bitdeq.pop_front();
+ assert(ref == bitref); // references to other elements are not invalidated
+ }
+ }
+ },
+ [&] {
+ // erase (in middle, single)
+ if (!cdeq.empty()) {
+ size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1);
+ size_t after = cdeq.size() - 1 - before;
+ auto it = deq.erase(cdeq.begin() + before);
+ auto bitit = bitdeq.erase(cbitdeq.begin() + before);
+ assert(it == cdeq.begin() + before && it == cdeq.end() - after);
+ assert(bitit == cbitdeq.begin() + before && bitit == cbitdeq.end() - after);
+ }
+ },
+ [&] {
+ // erase (at front, range)
+ size_t count = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size());
+ auto it = deq.erase(cdeq.begin(), cdeq.begin() + count);
+ auto bitit = bitdeq.erase(cbitdeq.begin(), cbitdeq.begin() + count);
+ assert(it == deq.begin());
+ assert(bitit == bitdeq.begin());
+ },
+ [&] {
+ // erase (at back, range)
+ size_t count = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size());
+ auto it = deq.erase(cdeq.end() - count, cdeq.end());
+ auto bitit = bitdeq.erase(cbitdeq.end() - count, cbitdeq.end());
+ assert(it == deq.end());
+ assert(bitit == bitdeq.end());
+ },
+ [&] {
+ // erase (in middle, range)
+ size_t count = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size());
+ size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - count);
+ size_t after = cdeq.size() - count - before;
+ auto it = deq.erase(cdeq.begin() + before, cdeq.end() - after);
+ auto bitit = bitdeq.erase(cbitdeq.begin() + before, cbitdeq.end() - after);
+ assert(it == cdeq.begin() + before && it == cdeq.end() - after);
+ assert(bitit == cbitdeq.begin() + before && bitit == cbitdeq.end() - after);
+ },
+ [&] {
+ // insert/emplace (in middle, single)
+ if (cdeq.size() < limitlen) {
+ size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size());
+ bool val = ctx.randbool();
+ bool do_emplace = provider.ConsumeBool();
+ auto it = deq.insert(cdeq.begin() + before, val);
+ auto bitit = do_emplace ? bitdeq.emplace(cbitdeq.begin() + before, val)
+ : bitdeq.insert(cbitdeq.begin() + before, val);
+ assert(it == deq.begin() + before);
+ assert(bitit == bitdeq.begin() + before);
+ }
+ },
+ [&] {
+ // insert (at front, begin/end)
+ if (cdeq.size() < limitlen) {
+ size_t count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS);
+ auto rand_end = rand_begin + count;
+ auto it = deq.insert(cdeq.begin(), rand_begin, rand_end);
+ auto bitit = bitdeq.insert(cbitdeq.begin(), rand_begin, rand_end);
+ assert(it == cdeq.begin());
+ assert(bitit == cbitdeq.begin());
+ }
+ },
+ [&] {
+ // insert (at back, begin/end)
+ if (cdeq.size() < limitlen) {
+ size_t count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS);
+ auto rand_end = rand_begin + count;
+ auto it = deq.insert(cdeq.end(), rand_begin, rand_end);
+ auto bitit = bitdeq.insert(cbitdeq.end(), rand_begin, rand_end);
+ assert(it == cdeq.end() - count);
+ assert(bitit == cbitdeq.end() - count);
+ }
+ },
+ [&] {
+ // insert (in middle, range)
+ if (cdeq.size() < limitlen) {
+ size_t count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size());
+ bool val = ctx.randbool();
+ auto it = deq.insert(cdeq.begin() + before, count, val);
+ auto bitit = bitdeq.insert(cbitdeq.begin() + before, count, val);
+ assert(it == deq.begin() + before);
+ assert(bitit == bitdeq.begin() + before);
+ }
+ },
+ [&] {
+ // insert (in middle, begin/end)
+ if (cdeq.size() < limitlen) {
+ size_t count = provider.ConsumeIntegralInRange<size_t>(0, maxlen);
+ size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size());
+ auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS);
+ auto rand_end = rand_begin + count;
+ auto it = deq.insert(cdeq.begin() + before, rand_begin, rand_end);
+ auto bitit = bitdeq.insert(cbitdeq.begin() + before, rand_begin, rand_end);
+ assert(it == deq.begin() + before);
+ assert(bitit == bitdeq.begin() + before);
+ }
+ }
+ );
+ }
+}
diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp
index 8c0ed32d51..01edb06138 100644
--- a/src/test/fuzz/chain.cpp
+++ b/src/test/fuzz/chain.cpp
@@ -23,7 +23,7 @@ FUZZ_TARGET(chain)
disk_block_index->phashBlock = &zero;
{
LOCK(::cs_main);
- (void)disk_block_index->GetBlockHash();
+ (void)disk_block_index->ConstructBlockHash();
(void)disk_block_index->GetBlockPos();
(void)disk_block_index->GetBlockTime();
(void)disk_block_index->GetBlockTimeMax();
@@ -31,7 +31,6 @@ FUZZ_TARGET(chain)
(void)disk_block_index->GetUndoPos();
(void)disk_block_index->HaveTxsDownloaded();
(void)disk_block_index->IsValid();
- (void)disk_block_index->ToString();
}
const CBlockHeader block_header = disk_block_index->GetBlockHeader();
diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp
index 72574612a2..c52fca5fe8 100644
--- a/src/test/fuzz/integer.cpp
+++ b/src/test/fuzz/integer.cpp
@@ -87,9 +87,6 @@ FUZZ_TARGET_INIT(integer, initialize_integer)
}
(void)GetSizeOfCompactSize(u64);
(void)GetSpecialScriptSize(u32);
- if (!MultiplicationOverflow(i64, static_cast<int64_t>(::nBytesPerSigOp)) && !AdditionOverflow(i64 * ::nBytesPerSigOp, static_cast<int64_t>(4))) {
- (void)GetVirtualTransactionSize(i64, i64);
- }
if (!MultiplicationOverflow(i64, static_cast<int64_t>(u32)) && !AdditionOverflow(i64, static_cast<int64_t>(4)) && !AdditionOverflow(i64 * u32, static_cast<int64_t>(4))) {
(void)GetVirtualTransactionSize(i64, i64, u32);
}
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index bfea9778f4..a76901e473 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -138,8 +138,6 @@ FUZZ_TARGET_INIT(key, initialize_key)
assert(tx_multisig_script.size() == 37);
FillableSigningProvider fillable_signing_provider;
- assert(IsSolvable(fillable_signing_provider, tx_pubkey_script));
- assert(IsSolvable(fillable_signing_provider, tx_multisig_script));
assert(!IsSegWitOutput(fillable_signing_provider, tx_pubkey_script));
assert(!IsSegWitOutput(fillable_signing_provider, tx_multisig_script));
assert(fillable_signing_provider.GetKeys().size() == 0);
@@ -157,12 +155,12 @@ FUZZ_TARGET_INIT(key, initialize_key)
assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
TxoutType which_type_tx_pubkey;
- const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
+ const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, std::nullopt, which_type_tx_pubkey);
assert(is_standard_tx_pubkey);
assert(which_type_tx_pubkey == TxoutType::PUBKEY);
TxoutType which_type_tx_multisig;
- const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
+ const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, std::nullopt, which_type_tx_multisig);
assert(is_standard_tx_multisig);
assert(which_type_tx_multisig == TxoutType::MULTISIG);
diff --git a/src/test/fuzz/load_external_block_file.cpp b/src/test/fuzz/load_external_block_file.cpp
index bfa977520b..f4b7dc08fd 100644
--- a/src/test/fuzz/load_external_block_file.cpp
+++ b/src/test/fuzz/load_external_block_file.cpp
@@ -31,6 +31,13 @@ FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
if (fuzzed_block_file == nullptr) {
return;
}
- FlatFilePos flat_file_pos;
- g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file, fuzzed_data_provider.ConsumeBool() ? &flat_file_pos : nullptr);
+ if (fuzzed_data_provider.ConsumeBool()) {
+ // Corresponds to the -reindex case (track orphan blocks across files).
+ FlatFilePos flat_file_pos;
+ std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
+ g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file, &flat_file_pos, &blocks_with_unknown_parent);
+ } else {
+ // Corresponds to the -loadblock= case (orphan blocks aren't tracked across files).
+ g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file);
+ }
}
diff --git a/src/test/fuzz/mempool_utils.h b/src/test/fuzz/mempool_utils.h
new file mode 100644
index 0000000000..c172e8c4b7
--- /dev/null
+++ b/src/test/fuzz/mempool_utils.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_FUZZ_MEMPOOL_UTILS_H
+#define BITCOIN_TEST_FUZZ_MEMPOOL_UTILS_H
+
+#include <validation.h>
+
+class DummyChainState final : public Chainstate
+{
+public:
+ void SetMempool(CTxMemPool* mempool)
+ {
+ m_mempool = mempool;
+ }
+};
+
+#endif // BITCOIN_TEST_FUZZ_MEMPOOL_UTILS_H
diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp
index 4981287152..741810f6a2 100644
--- a/src/test/fuzz/net.cpp
+++ b/src/test/fuzz/net.cpp
@@ -68,7 +68,6 @@ FUZZ_TARGET_INIT(net, initialize_net)
(void)node.GetAddrLocal();
(void)node.GetId();
(void)node.GetLocalNonce();
- (void)node.GetLocalServices();
const int ref_count = node.GetRefCount();
assert(ref_count >= 0);
(void)node.GetCommonVersion();
diff --git a/src/test/fuzz/node_eviction.cpp b/src/test/fuzz/node_eviction.cpp
index 6a363f00f7..e27b254580 100644
--- a/src/test/fuzz/node_eviction.cpp
+++ b/src/test/fuzz/node_eviction.cpp
@@ -32,6 +32,8 @@ FUZZ_TARGET(node_eviction)
/*prefer_evict=*/fuzzed_data_provider.ConsumeBool(),
/*m_is_local=*/fuzzed_data_provider.ConsumeBool(),
/*m_network=*/fuzzed_data_provider.PickValueInArray(ALL_NETWORKS),
+ /*m_noban=*/fuzzed_data_provider.ConsumeBool(),
+ /*m_conn_type=*/fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES),
});
}
// Make a copy since eviction_candidates may be in some valid but otherwise
diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp
index c7a76aa52f..0cc210f26f 100644
--- a/src/test/fuzz/parse_univalue.cpp
+++ b/src/test/fuzz/parse_univalue.cpp
@@ -26,7 +26,7 @@ FUZZ_TARGET_INIT(parse_univalue, initialize_parse_univalue)
return ParseNonRFCJSONValue(random_string);
} catch (const std::runtime_error&) {
valid = false;
- return NullUniValue;
+ return UniValue{};
}
}();
if (!valid) {
diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp
index e4d95f72a0..637ba503c6 100644
--- a/src/test/fuzz/policy_estimator.cpp
+++ b/src/test/fuzz/policy_estimator.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <policy/fees.h>
+#include <policy/fees_args.h>
#include <primitives/transaction.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
@@ -15,15 +16,20 @@
#include <string>
#include <vector>
+namespace {
+const BasicTestingSetup* g_setup;
+} // namespace
+
void initialize_policy_estimator()
{
static const auto testing_setup = MakeNoLogFileContext<>();
+ g_setup = testing_setup.get();
}
FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- CBlockPolicyEstimator block_policy_estimator;
+ CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args)};
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
CallOneOf(
fuzzed_data_provider,
@@ -70,7 +76,7 @@ FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator)
}
{
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
- CAutoFile fuzzed_auto_file = fuzzed_auto_file_provider.open();
+ AutoFile fuzzed_auto_file{fuzzed_auto_file_provider.open()};
block_policy_estimator.Write(fuzzed_auto_file);
block_policy_estimator.Read(fuzzed_auto_file);
}
diff --git a/src/test/fuzz/policy_estimator_io.cpp b/src/test/fuzz/policy_estimator_io.cpp
index 9021d95954..436873c955 100644
--- a/src/test/fuzz/policy_estimator_io.cpp
+++ b/src/test/fuzz/policy_estimator_io.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <policy/fees.h>
+#include <policy/fees_args.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
@@ -11,18 +12,23 @@
#include <cstdint>
#include <vector>
+namespace {
+const BasicTestingSetup* g_setup;
+} // namespace
+
void initialize_policy_estimator_io()
{
static const auto testing_setup = MakeNoLogFileContext<>();
+ g_setup = testing_setup.get();
}
FUZZ_TARGET_INIT(policy_estimator_io, initialize_policy_estimator_io)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
- CAutoFile fuzzed_auto_file = fuzzed_auto_file_provider.open();
+ AutoFile fuzzed_auto_file{fuzzed_auto_file_provider.open()};
// Re-using block_policy_estimator across runs to avoid costly creation of CBlockPolicyEstimator object.
- static CBlockPolicyEstimator block_policy_estimator;
+ static CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args)};
if (block_policy_estimator.Read(fuzzed_auto_file)) {
block_policy_estimator.Write(fuzzed_auto_file);
}
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp
index 0004d82d66..eba03da773 100644
--- a/src/test/fuzz/pow.cpp
+++ b/src/test/fuzz/pow.cpp
@@ -83,3 +83,40 @@ FUZZ_TARGET_INIT(pow, initialize_pow)
}
}
}
+
+
+FUZZ_TARGET_INIT(pow_transition, initialize_pow)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ const Consensus::Params& consensus_params{Params().GetConsensus()};
+ std::vector<std::unique_ptr<CBlockIndex>> blocks;
+
+ const uint32_t old_time{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+ const uint32_t new_time{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+ const int32_t version{fuzzed_data_provider.ConsumeIntegral<int32_t>()};
+ uint32_t nbits{fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+
+ const arith_uint256 pow_limit = UintToArith256(consensus_params.powLimit);
+ arith_uint256 old_target;
+ old_target.SetCompact(nbits);
+ if (old_target > pow_limit) {
+ nbits = pow_limit.GetCompact();
+ }
+ // Create one difficulty adjustment period worth of headers
+ for (int height = 0; height < consensus_params.DifficultyAdjustmentInterval(); ++height) {
+ CBlockHeader header;
+ header.nVersion = version;
+ header.nTime = old_time;
+ header.nBits = nbits;
+ if (height == consensus_params.DifficultyAdjustmentInterval() - 1) {
+ header.nTime = new_time;
+ }
+ auto current_block{std::make_unique<CBlockIndex>(header)};
+ current_block->pprev = blocks.empty() ? nullptr : blocks.back().get();
+ current_block->nHeight = height;
+ blocks.emplace_back(std::move(current_block));
+ }
+ auto last_block{blocks.back().get()};
+ unsigned int new_nbits{GetNextWorkRequired(last_block, nullptr, consensus_params)};
+ Assert(PermittedDifficultyTransition(consensus_params, last_block->nHeight + 1, last_block->nBits, new_nbits));
+}
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index 1763cd8af3..272c9e6cdc 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -80,8 +80,7 @@ void fuzz_target(FuzzBufferType buffer, const std::string& LIMIT_TO_MESSAGE_TYPE
CNode& p2p_node = *ConsumeNodeAsUniquePtr(fuzzed_data_provider).release();
connman.AddTestNode(p2p_node);
- g_setup->m_node.peerman->InitializeNode(&p2p_node);
- FillNode(fuzzed_data_provider, connman, *g_setup->m_node.peerman, p2p_node);
+ FillNode(fuzzed_data_provider, connman, p2p_node);
const auto mock_time = ConsumeTime(fuzzed_data_provider);
SetMockTime(mock_time);
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
index e1c11e1afd..12e682416c 100644
--- a/src/test/fuzz/process_messages.cpp
+++ b/src/test/fuzz/process_messages.cpp
@@ -46,8 +46,7 @@ FUZZ_TARGET_INIT(process_messages, initialize_process_messages)
peers.push_back(ConsumeNodeAsUniquePtr(fuzzed_data_provider, i).release());
CNode& p2p_node = *peers.back();
- g_setup->m_node.peerman->InitializeNode(&p2p_node);
- FillNode(fuzzed_data_provider, connman, *g_setup->m_node.peerman, p2p_node);
+ FillNode(fuzzed_data_provider, connman, p2p_node);
connman.AddTestNode(p2p_node);
}
diff --git a/src/test/fuzz/rbf.cpp b/src/test/fuzz/rbf.cpp
index 8dcaa609b5..1a06ae886e 100644
--- a/src/test/fuzz/rbf.cpp
+++ b/src/test/fuzz/rbf.cpp
@@ -2,12 +2,14 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <node/mempool_args.h>
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <sync.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
+#include <test/util/setup_common.h>
#include <txmempool.h>
#include <cstdint>
@@ -15,7 +17,17 @@
#include <string>
#include <vector>
-FUZZ_TARGET(rbf)
+namespace {
+const BasicTestingSetup* g_setup;
+} // namespace
+
+void initialize_rbf()
+{
+ static const auto testing_setup = MakeNoLogFileContext<>();
+ g_setup = testing_setup.get();
+}
+
+FUZZ_TARGET_INIT(rbf, initialize_rbf)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
SetMockTime(ConsumeTime(fuzzed_data_provider));
@@ -23,8 +35,11 @@ FUZZ_TARGET(rbf)
if (!mtx) {
return;
}
- CTxMemPool pool;
- LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
+
+ CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node)};
+
+ LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
+ {
const std::optional<CMutableTransaction> another_mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!another_mtx) {
break;
diff --git a/src/test/fuzz/rpc.cpp b/src/test/fuzz/rpc.cpp
index e4e83c3f32..26913a41d2 100644
--- a/src/test/fuzz/rpc.cpp
+++ b/src/test/fuzz/rpc.cpp
@@ -159,6 +159,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
"signrawtransactionwithkey",
"submitblock",
"submitheader",
+ "submitpackage",
"syncwithvalidationinterfacequeue",
"testmempoolaccept",
"uptime",
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index fdcd0da37d..00d7b7e29a 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -55,7 +55,7 @@ FUZZ_TARGET_INIT(script, initialize_script)
}
TxoutType which_type;
- bool is_standard_ret = IsStandard(script, which_type);
+ bool is_standard_ret = IsStandard(script, std::nullopt, which_type);
if (!is_standard_ret) {
assert(which_type == TxoutType::NONSTANDARD ||
which_type == TxoutType::NULL_DATA ||
@@ -89,7 +89,6 @@ FUZZ_TARGET_INIT(script, initialize_script)
const FlatSigningProvider signing_provider;
(void)InferDescriptor(script, signing_provider);
(void)IsSegWitOutput(signing_provider, script);
- (void)IsSolvable(signing_provider, script);
(void)RecursiveDynamicUsage(script);
diff --git a/src/test/fuzz/script_sigcache.cpp b/src/test/fuzz/script_sigcache.cpp
index f7e45d6889..f6af7947df 100644
--- a/src/test/fuzz/script_sigcache.cpp
+++ b/src/test/fuzz/script_sigcache.cpp
@@ -10,18 +10,21 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
+#include <test/util/setup_common.h>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
+namespace {
+const BasicTestingSetup* g_setup;
+} // namespace
+
void initialize_script_sigcache()
{
- static const ECCVerifyHandle ecc_verify_handle;
- ECC_Start();
- SelectParams(CBaseChainParams::REGTEST);
- InitSignatureCache();
+ static const auto testing_setup = MakeNoLogFileContext<>();
+ g_setup = testing_setup.get();
}
FUZZ_TARGET_INIT(script_sigcache, initialize_script_sigcache)
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index 273aa0dc5c..7fa4523800 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -69,8 +69,8 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
std::string reason;
- const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
- const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
+ const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ true, dust_relay_fee, reason);
+ const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, std::nullopt, /* permit_bare_multisig= */ false, dust_relay_fee, reason);
if (is_standard_without_permit_bare_multisig) {
assert(is_standard_with_permit_bare_multisig);
}
@@ -92,7 +92,6 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
(void)GetTransactionWeight(tx);
(void)GetVirtualTransactionSize(tx);
(void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024);
- (void)IsStandardTx(tx, reason);
(void)RecursiveDynamicUsage(tx);
(void)SignalsOptInRBF(tx);
diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp
index 4f40608c4f..283a146369 100644
--- a/src/test/fuzz/tx_pool.cpp
+++ b/src/test/fuzz/tx_pool.cpp
@@ -3,9 +3,12 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <consensus/validation.h>
+#include <node/context.h>
+#include <node/mempool_args.h>
#include <node/miner.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
+#include <test/fuzz/mempool_utils.h>
#include <test/fuzz/util.h>
#include <test/util/mining.h>
#include <test/util/script.h>
@@ -15,6 +18,7 @@
#include <validationinterface.h>
using node::BlockAssembler;
+using node::NodeContext;
namespace {
@@ -31,15 +35,6 @@ struct MockedTxPool : public CTxMemPool {
}
};
-class DummyChainState final : public CChainState
-{
-public:
- void SetMempool(CTxMemPool* mempool)
- {
- m_mempool = mempool;
- }
-};
-
void initialize_tx_pool()
{
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
@@ -90,7 +85,7 @@ void SetMempoolConstraints(ArgsManager& args, FuzzedDataProvider& fuzzed_data_pr
ToString(fuzzed_data_provider.ConsumeIntegralInRange<unsigned>(0, 999)));
}
-void Finish(FuzzedDataProvider& fuzzed_data_provider, MockedTxPool& tx_pool, CChainState& chainstate)
+void Finish(FuzzedDataProvider& fuzzed_data_provider, MockedTxPool& tx_pool, Chainstate& chainstate)
{
WITH_LOCK(::cs_main, tx_pool.check(chainstate.CoinsTip(), chainstate.m_chain.Height() + 1));
{
@@ -113,7 +108,7 @@ void Finish(FuzzedDataProvider& fuzzed_data_provider, MockedTxPool& tx_pool, CCh
SyncWithValidationInterfaceQueue();
}
-void MockTime(FuzzedDataProvider& fuzzed_data_provider, const CChainState& chainstate)
+void MockTime(FuzzedDataProvider& fuzzed_data_provider, const Chainstate& chainstate)
{
const auto time = ConsumeTime(fuzzed_data_provider,
chainstate.m_chain.Tip()->GetMedianTimePast() + 1,
@@ -121,6 +116,20 @@ void MockTime(FuzzedDataProvider& fuzzed_data_provider, const CChainState& chain
SetMockTime(time);
}
+CTxMemPool MakeMempool(FuzzedDataProvider& fuzzed_data_provider, const NodeContext& node)
+{
+ // Take the default options for tests...
+ CTxMemPool::Options mempool_opts{MemPoolOptionsForTest(node)};
+
+ // ...override specific options for this specific fuzz suite
+ mempool_opts.estimator = nullptr;
+ mempool_opts.check_ratio = 1;
+ mempool_opts.require_standard = fuzzed_data_provider.ConsumeBool();
+
+ // ...and construct a CTxMemPool from it
+ return CTxMemPool{mempool_opts};
+}
+
FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
@@ -128,7 +137,6 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
auto& chainstate{static_cast<DummyChainState&>(node.chainman->ActiveChainstate())};
MockTime(fuzzed_data_provider, chainstate);
- SetMempoolConstraints(*node.args, fuzzed_data_provider);
// All RBF-spendable outpoints
std::set<COutPoint> outpoints_rbf;
@@ -142,7 +150,8 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
// The sum of the values of all spendable outpoints
constexpr CAmount SUPPLY_TOTAL{COINBASE_MATURITY * 50 * COIN};
- CTxMemPool tx_pool_{/*estimator=*/nullptr, /*check_ratio=*/1};
+ SetMempoolConstraints(*node.args, fuzzed_data_provider);
+ CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
chainstate.SetMempool(&tx_pool);
@@ -213,9 +222,6 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
MockTime(fuzzed_data_provider, chainstate);
}
if (fuzzed_data_provider.ConsumeBool()) {
- SetMempoolConstraints(*node.args, fuzzed_data_provider);
- }
- if (fuzzed_data_provider.ConsumeBool()) {
tx_pool.RollingFeeUpdate();
}
if (fuzzed_data_provider.ConsumeBool()) {
@@ -232,7 +238,6 @@ FUZZ_TARGET_INIT(tx_pool_standard, initialize_tx_pool)
auto txr = std::make_shared<TransactionsDelta>(removed, added);
RegisterSharedValidationInterface(txr);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
- ::fRequireStandard = fuzzed_data_provider.ConsumeBool();
// Make sure ProcessNewPackage on one transaction works.
// The result is not guaranteed to be the same as what is returned by ATMP.
@@ -308,7 +313,6 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
auto& chainstate = node.chainman->ActiveChainstate();
MockTime(fuzzed_data_provider, chainstate);
- SetMempoolConstraints(*node.args, fuzzed_data_provider);
std::vector<uint256> txids;
for (const auto& outpoint : g_outpoints_coinbase_init_mature) {
@@ -320,7 +324,8 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
txids.push_back(ConsumeUInt256(fuzzed_data_provider));
}
- CTxMemPool tx_pool_{/*estimator=*/nullptr, /*check_ratio=*/1};
+ SetMempoolConstraints(*node.args, fuzzed_data_provider);
+ CTxMemPool tx_pool_{MakeMempool(fuzzed_data_provider, node)};
MockedTxPool& tx_pool = *static_cast<MockedTxPool*>(&tx_pool_);
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300)
@@ -331,9 +336,6 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
MockTime(fuzzed_data_provider, chainstate);
}
if (fuzzed_data_provider.ConsumeBool()) {
- SetMempoolConstraints(*node.args, fuzzed_data_provider);
- }
- if (fuzzed_data_provider.ConsumeBool()) {
tx_pool.RollingFeeUpdate();
}
if (fuzzed_data_provider.ConsumeBool()) {
@@ -346,7 +348,6 @@ FUZZ_TARGET_INIT(tx_pool, initialize_tx_pool)
const auto tx = MakeTransactionRef(mut_tx);
const bool bypass_limits = fuzzed_data_provider.ConsumeBool();
- ::fRequireStandard = fuzzed_data_provider.ConsumeBool();
const auto res = WITH_LOCK(::cs_main, return AcceptToMemoryPool(chainstate, tx, GetTime(), bypass_limits, /*test_accept=*/false));
const bool accepted = res.m_result_type == MempoolAcceptResult::ResultType::VALID;
if (accepted) {
diff --git a/src/test/fuzz/txorphan.cpp b/src/test/fuzz/txorphan.cpp
new file mode 100644
index 0000000000..55060f31cf
--- /dev/null
+++ b/src/test/fuzz/txorphan.cpp
@@ -0,0 +1,146 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/amount.h>
+#include <consensus/validation.h>
+#include <net_processing.h>
+#include <node/eviction.h>
+#include <policy/policy.h>
+#include <primitives/transaction.h>
+#include <script/script.h>
+#include <sync.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <test/util/setup_common.h>
+#include <txorphanage.h>
+#include <uint256.h>
+#include <util/check.h>
+#include <util/time.h>
+
+#include <cstdint>
+#include <memory>
+#include <set>
+#include <utility>
+#include <vector>
+
+void initialize_orphanage()
+{
+ static const auto testing_setup = MakeNoLogFileContext();
+}
+
+FUZZ_TARGET_INIT(txorphan, initialize_orphanage)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
+
+ TxOrphanage orphanage;
+ std::set<uint256> orphan_work_set;
+ std::vector<COutPoint> outpoints;
+ // initial outpoints used to construct transactions later
+ for (uint8_t i = 0; i < 4; i++) {
+ outpoints.emplace_back(uint256{i}, 0);
+ }
+ // if true, allow duplicate input when constructing tx
+ const bool duplicate_input = fuzzed_data_provider.ConsumeBool();
+
+ LIMITED_WHILE(outpoints.size() < 200'000 && fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS)
+ {
+ // construct transaction
+ const CTransactionRef tx = [&] {
+ CMutableTransaction tx_mut;
+ const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size());
+ const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, outpoints.size());
+ // pick unique outpoints from outpoints as input
+ for (uint32_t i = 0; i < num_in; i++) {
+ auto& prevout = PickValue(fuzzed_data_provider, outpoints);
+ tx_mut.vin.emplace_back(prevout);
+ // pop the picked outpoint if duplicate input is not allowed
+ if (!duplicate_input) {
+ std::swap(prevout, outpoints.back());
+ outpoints.pop_back();
+ }
+ }
+ // output amount will not affect txorphanage
+ for (uint32_t i = 0; i < num_out; i++) {
+ tx_mut.vout.emplace_back(CAmount{0}, CScript{});
+ }
+ // restore previously popped outpoints
+ for (auto& in : tx_mut.vin) {
+ outpoints.push_back(in.prevout);
+ }
+ const auto new_tx = MakeTransactionRef(tx_mut);
+ // add newly constructed transaction to outpoints
+ for (uint32_t i = 0; i < num_out; i++) {
+ outpoints.emplace_back(new_tx->GetHash(), i);
+ }
+ return new_tx;
+ }();
+
+ // trigger orphanage functions
+ LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10 * DEFAULT_MAX_ORPHAN_TRANSACTIONS)
+ {
+ NodeId peer_id = fuzzed_data_provider.ConsumeIntegral<NodeId>();
+
+ CallOneOf(
+ fuzzed_data_provider,
+ [&] {
+ LOCK(g_cs_orphans);
+ orphanage.AddChildrenToWorkSet(*tx, orphan_work_set);
+ },
+ [&] {
+ bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash()));
+ {
+ LOCK(g_cs_orphans);
+ bool get_tx = orphanage.GetTx(tx->GetHash()).first != nullptr;
+ Assert(have_tx == get_tx);
+ }
+ },
+ [&] {
+ bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash()));
+ // AddTx should return false if tx is too big or already have it
+ // tx weight is unknown, we only check when tx is already in orphanage
+ {
+ LOCK(g_cs_orphans);
+ bool add_tx = orphanage.AddTx(tx, peer_id);
+ // have_tx == true -> add_tx == false
+ Assert(!have_tx || !add_tx);
+ }
+ have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash()));
+ {
+ LOCK(g_cs_orphans);
+ bool add_tx = orphanage.AddTx(tx, peer_id);
+ // if have_tx is still false, it must be too big
+ Assert(!have_tx == (GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT));
+ Assert(!have_tx || !add_tx);
+ }
+ },
+ [&] {
+ bool have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash()));
+ // EraseTx should return 0 if m_orphans doesn't have the tx
+ {
+ LOCK(g_cs_orphans);
+ Assert(have_tx == orphanage.EraseTx(tx->GetHash()));
+ }
+ have_tx = orphanage.HaveTx(GenTxid::Txid(tx->GetHash())) || orphanage.HaveTx(GenTxid::Wtxid(tx->GetHash()));
+ // have_tx should be false and EraseTx should fail
+ {
+ LOCK(g_cs_orphans);
+ Assert(!have_tx && !orphanage.EraseTx(tx->GetHash()));
+ }
+ },
+ [&] {
+ LOCK(g_cs_orphans);
+ orphanage.EraseForPeer(peer_id);
+ },
+ [&] {
+ // test mocktime and expiry
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
+ auto limit = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
+ WITH_LOCK(g_cs_orphans, orphanage.LimitOrphans(limit));
+ Assert(orphanage.Size() <= limit);
+ });
+ }
+ }
+}
diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp
index 883698aff1..38626d4bcf 100644
--- a/src/test/fuzz/util.cpp
+++ b/src/test/fuzz/util.cpp
@@ -24,10 +24,10 @@ FuzzedSock::FuzzedSock(FuzzedDataProvider& fuzzed_data_provider)
FuzzedSock::~FuzzedSock()
{
// Sock::~Sock() will be called after FuzzedSock::~FuzzedSock() and it will call
- // Sock::Reset() (not FuzzedSock::Reset()!) which will call CloseSocket(m_socket).
+ // close(m_socket) if m_socket is not INVALID_SOCKET.
// Avoid closing an arbitrary file descriptor (m_socket is just a random very high number which
// theoretically may concide with a real opened file descriptor).
- Reset();
+ m_socket = INVALID_SOCKET;
}
FuzzedSock& FuzzedSock::operator=(Sock&& other)
@@ -36,11 +36,6 @@ FuzzedSock& FuzzedSock::operator=(Sock&& other)
return *this;
}
-void FuzzedSock::Reset()
-{
- m_socket = INVALID_SOCKET;
-}
-
ssize_t FuzzedSock::Send(const void* data, size_t len, int flags) const
{
constexpr std::array send_errnos{
@@ -160,6 +155,45 @@ int FuzzedSock::Connect(const sockaddr*, socklen_t) const
return 0;
}
+int FuzzedSock::Bind(const sockaddr*, socklen_t) const
+{
+ // Have a permanent error at bind_errnos[0] because when the fuzzed data is exhausted
+ // SetFuzzedErrNo() will always set the global errno to bind_errnos[0]. We want to
+ // avoid this method returning -1 and setting errno to a temporary error (like EAGAIN)
+ // repeatedly because proper code should retry on temporary errors, leading to an
+ // infinite loop.
+ constexpr std::array bind_errnos{
+ EACCES,
+ EADDRINUSE,
+ EADDRNOTAVAIL,
+ EAGAIN,
+ };
+ if (m_fuzzed_data_provider.ConsumeBool()) {
+ SetFuzzedErrNo(m_fuzzed_data_provider, bind_errnos);
+ return -1;
+ }
+ return 0;
+}
+
+int FuzzedSock::Listen(int) const
+{
+ // Have a permanent error at listen_errnos[0] because when the fuzzed data is exhausted
+ // SetFuzzedErrNo() will always set the global errno to listen_errnos[0]. We want to
+ // avoid this method returning -1 and setting errno to a temporary error (like EAGAIN)
+ // repeatedly because proper code should retry on temporary errors, leading to an
+ // infinite loop.
+ constexpr std::array listen_errnos{
+ EADDRINUSE,
+ EINVAL,
+ EOPNOTSUPP,
+ };
+ if (m_fuzzed_data_provider.ConsumeBool()) {
+ SetFuzzedErrNo(m_fuzzed_data_provider, listen_errnos);
+ return -1;
+ }
+ return 0;
+}
+
std::unique_ptr<Sock> FuzzedSock::Accept(sockaddr* addr, socklen_t* addr_len) const
{
constexpr std::array accept_errnos{
@@ -206,6 +240,20 @@ int FuzzedSock::SetSockOpt(int, int, const void*, socklen_t) const
return 0;
}
+int FuzzedSock::GetSockName(sockaddr* name, socklen_t* name_len) const
+{
+ constexpr std::array getsockname_errnos{
+ ECONNRESET,
+ ENOBUFS,
+ };
+ if (m_fuzzed_data_provider.ConsumeBool()) {
+ SetFuzzedErrNo(m_fuzzed_data_provider, getsockname_errnos);
+ return -1;
+ }
+ *name_len = m_fuzzed_data_provider.ConsumeData(name, *name_len);
+ return 0;
+}
+
bool FuzzedSock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const
{
constexpr std::array wait_errnos{
@@ -241,57 +289,14 @@ bool FuzzedSock::IsConnected(std::string& errmsg) const
return false;
}
-void FillNode(FuzzedDataProvider& fuzzed_data_provider, ConnmanTestMsg& connman, PeerManager& peerman, CNode& node) noexcept
-{
- const bool successfully_connected{fuzzed_data_provider.ConsumeBool()};
- const ServiceFlags remote_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS);
- const NetPermissionFlags permission_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
- const int32_t version = fuzzed_data_provider.ConsumeIntegralInRange<int32_t>(MIN_PEER_PROTO_VERSION, std::numeric_limits<int32_t>::max());
- const bool relay_txs{fuzzed_data_provider.ConsumeBool()};
-
- const CNetMsgMaker mm{0};
-
- CSerializedNetMsg msg_version{
- mm.Make(NetMsgType::VERSION,
- version, //
- Using<CustomUintFormatter<8>>(remote_services), //
- int64_t{}, // dummy time
- int64_t{}, // ignored service bits
- CService{}, // dummy
- int64_t{}, // ignored service bits
- CService{}, // ignored
- uint64_t{1}, // dummy nonce
- std::string{}, // dummy subver
- int32_t{}, // dummy starting_height
- relay_txs),
- };
-
- (void)connman.ReceiveMsgFrom(node, msg_version);
- node.fPauseSend = false;
- connman.ProcessMessagesOnce(node);
- {
- LOCK(node.cs_sendProcessing);
- peerman.SendMessages(&node);
- }
- if (node.fDisconnect) return;
- assert(node.nVersion == version);
- assert(node.GetCommonVersion() == std::min(version, PROTOCOL_VERSION));
- assert(node.nServices == remote_services);
- CNodeStateStats statestats;
- assert(peerman.GetNodeStateStats(node.GetId(), statestats));
- assert(statestats.m_relay_txs == (relay_txs && !node.IsBlockOnlyConn()));
- node.m_permissionFlags = permission_flags;
- if (successfully_connected) {
- CSerializedNetMsg msg_verack{mm.Make(NetMsgType::VERACK)};
- (void)connman.ReceiveMsgFrom(node, msg_verack);
- node.fPauseSend = false;
- connman.ProcessMessagesOnce(node);
- {
- LOCK(node.cs_sendProcessing);
- peerman.SendMessages(&node);
- }
- assert(node.fSuccessfullyConnected == true);
- }
+void FillNode(FuzzedDataProvider& fuzzed_data_provider, ConnmanTestMsg& connman, CNode& node) noexcept
+{
+ connman.Handshake(node,
+ /*successfully_connected=*/fuzzed_data_provider.ConsumeBool(),
+ /*remote_services=*/ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS),
+ /*local_services=*/ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS),
+ /*version=*/fuzzed_data_provider.ConsumeIntegralInRange<int32_t>(MIN_PEER_PROTO_VERSION, std::numeric_limits<int32_t>::max()),
+ /*relay_txs=*/fuzzed_data_provider.ConsumeBool());
}
CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider, const std::optional<CAmount>& max) noexcept
@@ -521,6 +526,11 @@ CNetAddr ConsumeNetAddr(FuzzedDataProvider& fuzzed_data_provider) noexcept
return net_addr;
}
+CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ return {ConsumeService(fuzzed_data_provider), ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS), NodeSeconds{std::chrono::seconds{fuzzed_data_provider.ConsumeIntegral<uint32_t>()}}};
+}
+
FILE* FuzzedFileProvider::open()
{
SetFuzzedErrNo(m_fuzzed_data_provider);
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index 66d00b1767..6d652c922b 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -8,7 +8,7 @@
#include <arith_uint256.h>
#include <chainparamsbase.h>
#include <coins.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <consensus/amount.h>
#include <consensus/consensus.h>
#include <merkleblock.h>
@@ -55,20 +55,24 @@ public:
FuzzedSock& operator=(Sock&& other) override;
- void Reset() override;
-
ssize_t Send(const void* data, size_t len, int flags) const override;
ssize_t Recv(void* buf, size_t len, int flags) const override;
int Connect(const sockaddr*, socklen_t) const override;
+ int Bind(const sockaddr*, socklen_t) const override;
+
+ int Listen(int backlog) const override;
+
std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override;
int SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt_len) const override;
+ int GetSockName(sockaddr* name, socklen_t* name_len) const override;
+
bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override;
bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override;
@@ -283,16 +287,12 @@ inline CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcep
return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
}
-inline CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept
-{
- return {ConsumeService(fuzzed_data_provider), ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS), fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
-}
+CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept;
template <bool ReturnUniquePtr = false>
auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<NodeId>& node_id_in = std::nullopt) noexcept
{
const NodeId node_id = node_id_in.value_or(fuzzed_data_provider.ConsumeIntegralInRange<NodeId>(0, std::numeric_limits<NodeId>::max()));
- const ServiceFlags local_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS);
const auto sock = std::make_shared<FuzzedSock>(fuzzed_data_provider);
const CAddress address = ConsumeAddress(fuzzed_data_provider);
const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
@@ -301,9 +301,9 @@ auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<N
const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64);
const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES);
const bool inbound_onion{conn_type == ConnectionType::INBOUND ? fuzzed_data_provider.ConsumeBool() : false};
+ NetPermissionFlags permission_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
if constexpr (ReturnUniquePtr) {
return std::make_unique<CNode>(node_id,
- local_services,
sock,
address,
keyed_net_group,
@@ -311,10 +311,10 @@ auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<N
addr_bind,
addr_name,
conn_type,
- inbound_onion);
+ inbound_onion,
+ CNodeOptions{ .permission_flags = permission_flags });
} else {
return CNode{node_id,
- local_services,
sock,
address,
keyed_net_group,
@@ -322,12 +322,13 @@ auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<N
addr_bind,
addr_name,
conn_type,
- inbound_onion};
+ inbound_onion,
+ CNodeOptions{ .permission_flags = permission_flags }};
}
}
inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, const std::optional<NodeId>& node_id_in = std::nullopt) { return ConsumeNode<true>(fdp, node_id_in); }
-void FillNode(FuzzedDataProvider& fuzzed_data_provider, ConnmanTestMsg& connman, PeerManager& peerman, CNode& node) noexcept;
+void FillNode(FuzzedDataProvider& fuzzed_data_provider, ConnmanTestMsg& connman, CNode& node) noexcept;
class FuzzedFileProvider
{
@@ -357,17 +358,16 @@ public:
class FuzzedAutoFileProvider
{
- FuzzedDataProvider& m_fuzzed_data_provider;
FuzzedFileProvider m_fuzzed_file_provider;
public:
- FuzzedAutoFileProvider(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider{fuzzed_data_provider}, m_fuzzed_file_provider{fuzzed_data_provider}
+ FuzzedAutoFileProvider(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_file_provider{fuzzed_data_provider}
{
}
- CAutoFile open()
+ AutoFile open()
{
- return {m_fuzzed_file_provider.open(), m_fuzzed_data_provider.ConsumeIntegral<int>(), m_fuzzed_data_provider.ConsumeIntegral<int>()};
+ return AutoFile{m_fuzzed_file_provider.open()};
}
};
diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp
index 33496a457e..8abb943266 100644
--- a/src/test/fuzz/utxo_snapshot.cpp
+++ b/src/test/fuzz/utxo_snapshot.cpp
@@ -39,13 +39,13 @@ FUZZ_TARGET_INIT(utxo_snapshot, initialize_chain)
Assert(!chainman.SnapshotBlockhash());
{
- CAutoFile outfile{fsbridge::fopen(snapshot_path, "wb"), SER_DISK, CLIENT_VERSION};
+ AutoFile outfile{fsbridge::fopen(snapshot_path, "wb")};
const auto file_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
outfile << Span{file_data};
}
const auto ActivateFuzzedSnapshot{[&] {
- CAutoFile infile{fsbridge::fopen(snapshot_path, "rb"), SER_DISK, CLIENT_VERSION};
+ AutoFile infile{fsbridge::fopen(snapshot_path, "rb")};
SnapshotMetadata metadata;
try {
infile >> metadata;
@@ -58,7 +58,7 @@ FUZZ_TARGET_INIT(utxo_snapshot, initialize_chain)
if (fuzzed_data_provider.ConsumeBool()) {
for (const auto& block : *g_chain) {
BlockValidationState dummy;
- bool processed{chainman.ProcessNewBlockHeaders({*block}, dummy)};
+ bool processed{chainman.ProcessNewBlockHeaders({*block}, true, dummy)};
Assert(processed);
const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))};
Assert(index);
diff --git a/src/test/fuzz/validation_load_mempool.cpp b/src/test/fuzz/validation_load_mempool.cpp
index c2aaf486c5..8241dff189 100644
--- a/src/test/fuzz/validation_load_mempool.cpp
+++ b/src/test/fuzz/validation_load_mempool.cpp
@@ -2,9 +2,14 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <kernel/mempool_persist.h>
+
#include <chainparamsbase.h>
+#include <node/mempool_args.h>
+#include <node/mempool_persist_args.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
+#include <test/fuzz/mempool_utils.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <txmempool.h>
@@ -14,6 +19,10 @@
#include <cstdint>
#include <vector>
+using kernel::DumpMempool;
+
+using node::MempoolPath;
+
namespace {
const TestingSetup* g_setup;
} // namespace
@@ -30,10 +39,14 @@ FUZZ_TARGET_INIT(validation_load_mempool, initialize_validation_load_mempool)
SetMockTime(ConsumeTime(fuzzed_data_provider));
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
- CTxMemPool pool{};
+ CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node)};
+
+ auto& chainstate{static_cast<DummyChainState&>(g_setup->m_node.chainman->ActiveChainstate())};
+ chainstate.SetMempool(&pool);
+
auto fuzzed_fopen = [&](const fs::path&, const char*) {
return fuzzed_file_provider.open();
};
- (void)LoadMempool(pool, g_setup->m_node.chainman->ActiveChainstate(), fuzzed_fopen);
- (void)DumpMempool(pool, fuzzed_fopen, true);
+ (void)chainstate.LoadMempool(MempoolPath(g_setup->m_args), fuzzed_fopen);
+ (void)DumpMempool(pool, MempoolPath(g_setup->m_args), fuzzed_fopen, true);
}
diff --git a/src/test/headers_sync_chainwork_tests.cpp b/src/test/headers_sync_chainwork_tests.cpp
new file mode 100644
index 0000000000..41241ebee2
--- /dev/null
+++ b/src/test/headers_sync_chainwork_tests.cpp
@@ -0,0 +1,146 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chain.h>
+#include <chainparams.h>
+#include <consensus/params.h>
+#include <headerssync.h>
+#include <pow.h>
+#include <test/util/setup_common.h>
+#include <validation.h>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+struct HeadersGeneratorSetup : public RegTestingSetup {
+ /** Search for a nonce to meet (regtest) proof of work */
+ void FindProofOfWork(CBlockHeader& starting_header);
+ /**
+ * Generate headers in a chain that build off a given starting hash, using
+ * the given nVersion, advancing time by 1 second from the starting
+ * prev_time, and with a fixed merkle root hash.
+ */
+ void GenerateHeaders(std::vector<CBlockHeader>& headers, size_t count,
+ const uint256& starting_hash, const int nVersion, int prev_time,
+ const uint256& merkle_root, const uint32_t nBits);
+};
+
+void HeadersGeneratorSetup::FindProofOfWork(CBlockHeader& starting_header)
+{
+ while (!CheckProofOfWork(starting_header.GetHash(), starting_header.nBits, Params().GetConsensus())) {
+ ++(starting_header.nNonce);
+ }
+}
+
+void HeadersGeneratorSetup::GenerateHeaders(std::vector<CBlockHeader>& headers,
+ size_t count, const uint256& starting_hash, const int nVersion, int prev_time,
+ const uint256& merkle_root, const uint32_t nBits)
+{
+ uint256 prev_hash = starting_hash;
+
+ while (headers.size() < count) {
+ headers.push_back(CBlockHeader());
+ CBlockHeader& next_header = headers.back();;
+ next_header.nVersion = nVersion;
+ next_header.hashPrevBlock = prev_hash;
+ next_header.hashMerkleRoot = merkle_root;
+ next_header.nTime = prev_time+1;
+ next_header.nBits = nBits;
+
+ FindProofOfWork(next_header);
+ prev_hash = next_header.GetHash();
+ prev_time = next_header.nTime;
+ }
+ return;
+}
+
+BOOST_FIXTURE_TEST_SUITE(headers_sync_chainwork_tests, HeadersGeneratorSetup)
+
+// In this test, we construct two sets of headers from genesis, one with
+// sufficient proof of work and one without.
+// 1. We deliver the first set of headers and verify that the headers sync state
+// updates to the REDOWNLOAD phase successfully.
+// 2. Then we deliver the second set of headers and verify that they fail
+// processing (presumably due to commitments not matching).
+// 3. Finally, we verify that repeating with the first set of headers in both
+// phases is successful.
+BOOST_AUTO_TEST_CASE(headers_sync_state)
+{
+ std::vector<CBlockHeader> first_chain;
+ std::vector<CBlockHeader> second_chain;
+
+ std::unique_ptr<HeadersSyncState> hss;
+
+ const int target_blocks = 15000;
+ arith_uint256 chain_work = target_blocks*2;
+
+ // Generate headers for two different chains (using differing merkle roots
+ // to ensure the headers are different).
+ GenerateHeaders(first_chain, target_blocks-1, Params().GenesisBlock().GetHash(),
+ Params().GenesisBlock().nVersion, Params().GenesisBlock().nTime,
+ ArithToUint256(0), Params().GenesisBlock().nBits);
+
+ GenerateHeaders(second_chain, target_blocks-2, Params().GenesisBlock().GetHash(),
+ Params().GenesisBlock().nVersion, Params().GenesisBlock().nTime,
+ ArithToUint256(1), Params().GenesisBlock().nBits);
+
+ const CBlockIndex* chain_start = WITH_LOCK(::cs_main, return m_node.chainman->m_blockman.LookupBlockIndex(Params().GenesisBlock().GetHash()));
+ std::vector<CBlockHeader> headers_batch;
+
+ // Feed the first chain to HeadersSyncState, by delivering 1 header
+ // initially and then the rest.
+ headers_batch.insert(headers_batch.end(), std::next(first_chain.begin()), first_chain.end());
+
+ hss.reset(new HeadersSyncState(0, Params().GetConsensus(), chain_start, chain_work));
+ (void)hss->ProcessNextHeaders({first_chain.front()}, true);
+ // Pretend the first header is still "full", so we don't abort.
+ auto result = hss->ProcessNextHeaders(headers_batch, true);
+
+ // This chain should look valid, and we should have met the proof-of-work
+ // requirement.
+ BOOST_CHECK(result.success);
+ BOOST_CHECK(result.request_more);
+ BOOST_CHECK(hss->GetState() == HeadersSyncState::State::REDOWNLOAD);
+
+ // Try to sneakily feed back the second chain.
+ result = hss->ProcessNextHeaders(second_chain, true);
+ BOOST_CHECK(!result.success); // foiled!
+ BOOST_CHECK(hss->GetState() == HeadersSyncState::State::FINAL);
+
+ // Now try again, this time feeding the first chain twice.
+ hss.reset(new HeadersSyncState(0, Params().GetConsensus(), chain_start, chain_work));
+ (void)hss->ProcessNextHeaders(first_chain, true);
+ BOOST_CHECK(hss->GetState() == HeadersSyncState::State::REDOWNLOAD);
+
+ result = hss->ProcessNextHeaders(first_chain, true);
+ BOOST_CHECK(result.success);
+ BOOST_CHECK(!result.request_more);
+ // All headers should be ready for acceptance:
+ BOOST_CHECK(result.pow_validated_headers.size() == first_chain.size());
+ // Nothing left for the sync logic to do:
+ BOOST_CHECK(hss->GetState() == HeadersSyncState::State::FINAL);
+
+ // Finally, verify that just trying to process the second chain would not
+ // succeed (too little work)
+ hss.reset(new HeadersSyncState(0, Params().GetConsensus(), chain_start, chain_work));
+ BOOST_CHECK(hss->GetState() == HeadersSyncState::State::PRESYNC);
+ // Pretend just the first message is "full", so we don't abort.
+ (void)hss->ProcessNextHeaders({second_chain.front()}, true);
+ BOOST_CHECK(hss->GetState() == HeadersSyncState::State::PRESYNC);
+
+ headers_batch.clear();
+ headers_batch.insert(headers_batch.end(), std::next(second_chain.begin(), 1), second_chain.end());
+ // Tell the sync logic that the headers message was not full, implying no
+ // more headers can be requested. For a low-work-chain, this should causes
+ // the sync to end with no headers for acceptance.
+ result = hss->ProcessNextHeaders(headers_batch, false);
+ BOOST_CHECK(hss->GetState() == HeadersSyncState::State::FINAL);
+ BOOST_CHECK(result.pow_validated_headers.empty());
+ BOOST_CHECK(!result.request_more);
+ // Nevertheless, no validation errors should have been detected with the
+ // chain:
+ BOOST_CHECK(result.success);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/i2p_tests.cpp b/src/test/i2p_tests.cpp
index bd9ba4b8f7..9da1ee11f9 100644
--- a/src/test/i2p_tests.cpp
+++ b/src/test/i2p_tests.cpp
@@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <i2p.h>
+#include <logging.h>
#include <netaddress.h>
#include <test/util/logging.h>
#include <test/util/net.h>
@@ -19,6 +20,8 @@ BOOST_FIXTURE_TEST_SUITE(i2p_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(unlimited_recv)
{
+ const auto prev_log_level{LogInstance().LogLevel()};
+ LogInstance().SetLogLevel(BCLog::Level::Trace);
auto CreateSockOrig = CreateSock;
// Mock CreateSock() to create MockSock.
@@ -30,7 +33,7 @@ BOOST_AUTO_TEST_CASE(unlimited_recv)
i2p::sam::Session session(gArgs.GetDataDirNet() / "test_i2p_private_key", CService{}, &interrupt);
{
- ASSERT_DEBUG_LOG("Creating SAM session");
+ ASSERT_DEBUG_LOG("Creating persistent SAM session");
ASSERT_DEBUG_LOG("too many bytes without a terminator");
i2p::Connection conn;
@@ -39,6 +42,7 @@ BOOST_AUTO_TEST_CASE(unlimited_recv)
}
CreateSock = CreateSockOrig;
+ LogInstance().SetLogLevel(prev_log_level);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
index 49b7d2003b..cb901b2259 100644
--- a/src/test/interfaces_tests.cpp
+++ b/src/test/interfaces_tests.cpp
@@ -17,6 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(interfaces_tests, TestChain100Setup)
BOOST_AUTO_TEST_CASE(findBlock)
{
+ LOCK(Assert(m_node.chainman)->GetMutex());
auto& chain = m_node.chain;
const CChain& active = Assert(m_node.chainman)->ActiveChain();
@@ -61,6 +62,7 @@ BOOST_AUTO_TEST_CASE(findBlock)
BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
{
+ LOCK(Assert(m_node.chainman)->GetMutex());
auto& chain = m_node.chain;
const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
@@ -73,6 +75,7 @@ BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
BOOST_AUTO_TEST_CASE(findAncestorByHeight)
{
+ LOCK(Assert(m_node.chainman)->GetMutex());
auto& chain = m_node.chain;
const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
@@ -83,6 +86,7 @@ BOOST_AUTO_TEST_CASE(findAncestorByHeight)
BOOST_AUTO_TEST_CASE(findAncestorByHash)
{
+ LOCK(Assert(m_node.chainman)->GetMutex());
auto& chain = m_node.chain;
const CChain& active = Assert(m_node.chainman)->ActiveChain();
int height = -1;
@@ -94,7 +98,7 @@ BOOST_AUTO_TEST_CASE(findAncestorByHash)
BOOST_AUTO_TEST_CASE(findCommonAncestor)
{
auto& chain = m_node.chain;
- const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ const CChain& active = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return Assert(m_node.chainman)->ActiveChain());
auto* orig_tip = active.Tip();
for (int i = 0; i < 10; ++i) {
BlockValidationState state;
diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp
index e70b8b3dfd..1eac68de14 100644
--- a/src/test/key_io_tests.cpp
+++ b/src/test/key_io_tests.cpp
@@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(key_io_valid_parse)
SelectParams(CBaseChainParams::MAIN);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
if (test.size() < 3) { // Allow for extra stuff (useful for comments)
BOOST_ERROR("Bad test: " << strTest);
@@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(key_io_valid_gen)
UniValue tests = read_json(std::string(json_tests::key_io_valid, json_tests::key_io_valid + sizeof(json_tests::key_io_valid)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
if (test.size() < 3) // Allow for extra stuff (useful for comments)
{
@@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE(key_io_invalid)
CTxDestination destination;
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
if (test.size() < 1) // Allow for extra stuff (useful for comments)
{
diff --git a/src/test/logging_tests.cpp b/src/test/logging_tests.cpp
index 5a5e3b3f1f..a6f3a62c71 100644
--- a/src/test/logging_tests.cpp
+++ b/src/test/logging_tests.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <init/common.h>
#include <logging.h>
#include <logging/timer.h>
#include <test/util/setup_common.h>
@@ -10,6 +11,7 @@
#include <chrono>
#include <fstream>
#include <iostream>
+#include <unordered_map>
#include <utility>
#include <vector>
@@ -17,6 +19,12 @@
BOOST_FIXTURE_TEST_SUITE(logging_tests, BasicTestingSetup)
+static void ResetLogger()
+{
+ LogInstance().SetLogLevel(BCLog::DEFAULT_LOG_LEVEL);
+ LogInstance().SetCategoryLogLevel({});
+}
+
struct LogSetup : public BasicTestingSetup {
fs::path prev_log_path;
fs::path tmp_log_path;
@@ -25,6 +33,8 @@ struct LogSetup : public BasicTestingSetup {
bool prev_log_timestamps;
bool prev_log_threadnames;
bool prev_log_sourcelocations;
+ std::unordered_map<BCLog::LogFlags, BCLog::Level> prev_category_levels;
+ BCLog::Level prev_log_level;
LogSetup() : prev_log_path{LogInstance().m_file_path},
tmp_log_path{m_args.GetDataDirBase() / "tmp_debug.log"},
@@ -32,14 +42,21 @@ struct LogSetup : public BasicTestingSetup {
prev_print_to_file{LogInstance().m_print_to_file},
prev_log_timestamps{LogInstance().m_log_timestamps},
prev_log_threadnames{LogInstance().m_log_threadnames},
- prev_log_sourcelocations{LogInstance().m_log_sourcelocations}
+ prev_log_sourcelocations{LogInstance().m_log_sourcelocations},
+ prev_category_levels{LogInstance().CategoryLevels()},
+ prev_log_level{LogInstance().LogLevel()}
{
LogInstance().m_file_path = tmp_log_path;
LogInstance().m_reopen_file = true;
LogInstance().m_print_to_file = true;
LogInstance().m_log_timestamps = false;
LogInstance().m_log_threadnames = false;
- LogInstance().m_log_sourcelocations = true;
+
+ // Prevent tests from failing when the line number of the logs changes.
+ LogInstance().m_log_sourcelocations = false;
+
+ LogInstance().SetLogLevel(BCLog::Level::Debug);
+ LogInstance().SetCategoryLogLevel({});
}
~LogSetup()
@@ -51,6 +68,8 @@ struct LogSetup : public BasicTestingSetup {
LogInstance().m_log_timestamps = prev_log_timestamps;
LogInstance().m_log_threadnames = prev_log_threadnames;
LogInstance().m_log_sourcelocations = prev_log_sourcelocations;
+ LogInstance().SetLogLevel(prev_log_level);
+ LogInstance().SetCategoryLogLevel(prev_category_levels);
}
};
@@ -74,6 +93,7 @@ BOOST_AUTO_TEST_CASE(logging_timer)
BOOST_FIXTURE_TEST_CASE(logging_LogPrintf_, LogSetup)
{
+ LogInstance().m_log_sourcelocations = true;
LogPrintf_("fn1", "src1", 1, BCLog::LogFlags::NET, BCLog::Level::Debug, "foo1: %s", "bar1\n");
LogPrintf_("fn2", "src2", 2, BCLog::LogFlags::NET, BCLog::Level::None, "foo2: %s", "bar2\n");
LogPrintf_("fn3", "src3", 3, BCLog::LogFlags::NONE, BCLog::Level::Debug, "foo3: %s", "bar3\n");
@@ -94,9 +114,6 @@ BOOST_FIXTURE_TEST_CASE(logging_LogPrintf_, LogSetup)
BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros, LogSetup)
{
- // Prevent tests from failing when the line number of the following log calls changes.
- LogInstance().m_log_sourcelocations = false;
-
LogPrintf("foo5: %s\n", "bar5");
LogPrint(BCLog::NET, "foo6: %s\n", "bar6");
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "foo7: %s\n", "bar7");
@@ -123,16 +140,14 @@ BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros, LogSetup)
BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros_CategoryName, LogSetup)
{
- // Prevent tests from failing when the line number of the following log calls changes.
- LogInstance().m_log_sourcelocations = false;
LogInstance().EnableCategory(BCLog::LogFlags::ALL);
- const auto concated_categery_names = LogInstance().LogCategoriesString();
+ const auto concatenated_category_names = LogInstance().LogCategoriesString();
std::vector<std::pair<BCLog::LogFlags, std::string>> expected_category_names;
- const auto category_names = SplitString(concated_categery_names, ',');
+ const auto category_names = SplitString(concatenated_category_names, ',');
for (const auto& category_name : category_names) {
- BCLog::LogFlags category = BCLog::NONE;
+ BCLog::LogFlags category;
const auto trimmed_category_name = TrimString(category_name);
- BOOST_TEST(GetLogCategory(category, trimmed_category_name));
+ BOOST_REQUIRE(GetLogCategory(category, trimmed_category_name));
expected_category_names.emplace_back(category, trimmed_category_name);
}
@@ -153,4 +168,92 @@ BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros_CategoryName, LogSetup)
BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
}
+BOOST_FIXTURE_TEST_CASE(logging_SeverityLevels, LogSetup)
+{
+ LogInstance().EnableCategory(BCLog::LogFlags::ALL);
+
+ LogInstance().SetLogLevel(BCLog::Level::Debug);
+ LogInstance().SetCategoryLogLevel(/*category_str=*/"net", /*level_str=*/"info");
+
+ // Global log level
+ LogPrintLevel(BCLog::HTTP, BCLog::Level::Info, "foo1: %s\n", "bar1");
+ LogPrintLevel(BCLog::MEMPOOL, BCLog::Level::Trace, "foo2: %s. This log level is lower than the global one.\n", "bar2");
+ LogPrintLevel(BCLog::VALIDATION, BCLog::Level::Warning, "foo3: %s\n", "bar3");
+ LogPrintLevel(BCLog::RPC, BCLog::Level::Error, "foo4: %s\n", "bar4");
+
+ // Category-specific log level
+ LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "foo5: %s\n", "bar5");
+ LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "foo6: %s. This log level is the same as the global one but lower than the category-specific one, which takes precedence. \n", "bar6");
+ LogPrintLevel(BCLog::NET, BCLog::Level::Error, "foo7: %s\n", "bar7");
+
+ std::vector<std::string> expected = {
+ "[http:info] foo1: bar1",
+ "[validation:warning] foo3: bar3",
+ "[rpc:error] foo4: bar4",
+ "[net:warning] foo5: bar5",
+ "[net:error] foo7: bar7",
+ };
+ std::ifstream file{tmp_log_path};
+ std::vector<std::string> log_lines;
+ for (std::string log; std::getline(file, log);) {
+ log_lines.push_back(log);
+ }
+ BOOST_CHECK_EQUAL_COLLECTIONS(log_lines.begin(), log_lines.end(), expected.begin(), expected.end());
+}
+
+BOOST_FIXTURE_TEST_CASE(logging_Conf, LogSetup)
+{
+ // Set global log level
+ {
+ ResetLogger();
+ ArgsManager args;
+ args.AddArg("-loglevel", "...", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ const char* argv_test[] = {"bitcoind", "-loglevel=debug"};
+ std::string err;
+ BOOST_REQUIRE(args.ParseParameters(2, argv_test, err));
+ init::SetLoggingLevel(args);
+ BOOST_CHECK_EQUAL(LogInstance().LogLevel(), BCLog::Level::Debug);
+ }
+
+ // Set category-specific log level
+ {
+ ResetLogger();
+ ArgsManager args;
+ args.AddArg("-loglevel", "...", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ const char* argv_test[] = {"bitcoind", "-loglevel=net:trace"};
+ std::string err;
+ BOOST_REQUIRE(args.ParseParameters(2, argv_test, err));
+ init::SetLoggingLevel(args);
+ BOOST_CHECK_EQUAL(LogInstance().LogLevel(), BCLog::DEFAULT_LOG_LEVEL);
+
+ const auto& category_levels{LogInstance().CategoryLevels()};
+ const auto net_it{category_levels.find(BCLog::LogFlags::NET)};
+ BOOST_REQUIRE(net_it != category_levels.end());
+ BOOST_CHECK_EQUAL(net_it->second, BCLog::Level::Trace);
+ }
+
+ // Set both global log level and category-specific log level
+ {
+ ResetLogger();
+ ArgsManager args;
+ args.AddArg("-loglevel", "...", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ const char* argv_test[] = {"bitcoind", "-loglevel=debug", "-loglevel=net:trace", "-loglevel=http:info"};
+ std::string err;
+ BOOST_REQUIRE(args.ParseParameters(4, argv_test, err));
+ init::SetLoggingLevel(args);
+ BOOST_CHECK_EQUAL(LogInstance().LogLevel(), BCLog::Level::Debug);
+
+ const auto& category_levels{LogInstance().CategoryLevels()};
+ BOOST_CHECK_EQUAL(category_levels.size(), 2);
+
+ const auto net_it{category_levels.find(BCLog::LogFlags::NET)};
+ BOOST_CHECK(net_it != category_levels.end());
+ BOOST_CHECK_EQUAL(net_it->second, BCLog::Level::Trace);
+
+ const auto http_it{category_levels.find(BCLog::LogFlags::HTTP)};
+ BOOST_CHECK(http_it != category_levels.end());
+ BOOST_CHECK_EQUAL(http_it->second, BCLog::Level::Info);
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index bc63122025..8c745b07b9 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -16,6 +16,12 @@ BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup)
static constexpr auto REMOVAL_REASON_DUMMY = MemPoolRemovalReason::REPLACED;
+class MemPoolTest final : public CTxMemPool
+{
+public:
+ using CTxMemPool::GetMinFee;
+};
+
BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
{
// Test CTxMemPool::remove functionality
@@ -423,7 +429,7 @@ BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
{
- CTxMemPool& pool = *Assert(m_node.mempool);
+ auto& pool = static_cast<MemPoolTest&>(*Assert(m_node.mempool));
LOCK2(cs_main, pool.cs);
TestMemPoolEntryHelper entry;
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index eca4fbf15c..9f5fb17b60 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -325,7 +325,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
next->pprev = prev;
next->nHeight = prev->nHeight + 1;
next->BuildSkip();
- m_node.chainman->ActiveChain().SetTip(next);
+ m_node.chainman->ActiveChain().SetTip(*next);
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
// Extend to a 210000-long block chain.
@@ -337,7 +337,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
next->pprev = prev;
next->nHeight = prev->nHeight + 1;
next->BuildSkip();
- m_node.chainman->ActiveChain().SetTip(next);
+ m_node.chainman->ActiveChain().SetTip(*next);
}
BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
@@ -362,15 +362,15 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
// Delete the dummy blocks again.
while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {
CBlockIndex* del = m_node.chainman->ActiveChain().Tip();
- m_node.chainman->ActiveChain().SetTip(del->pprev);
+ m_node.chainman->ActiveChain().SetTip(*Assert(del->pprev));
m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(del->pprev->GetBlockHash());
delete del->phashBlock;
delete del;
}
// non-final txs in mempool
- SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1);
- const int flags{LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST};
+ SetMockTime(m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1);
+ const int flags{LOCKTIME_VERIFY_SEQUENCE};
// height map
std::vector<int> prevheights;
@@ -389,7 +389,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
tx.nLockTime = 0;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
- BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
{
@@ -403,7 +403,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
prevheights[0] = baseheight + 2;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
const int SEQUENCE_LOCK_TIME = 512; // Sequence locks pass 512 seconds later
@@ -426,7 +426,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
+ BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails
BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
@@ -437,7 +437,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
prevheights[0] = baseheight + 4;
hash = tx.GetHash();
m_node.mempool->addUnchecked(entry.Time(GetTime()).FromTx(tx));
- BOOST_CHECK(!CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime fails
+ BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails
BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
@@ -446,7 +446,7 @@ void MinerTestingSetup::TestBasicMining(const CChainParams& chainparams, const C
prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1;
tx.nLockTime = 0;
tx.vin[0].nSequence = 0;
- BOOST_CHECK(CheckFinalTxAtTip(m_node.chainman->ActiveChain().Tip(), CTransaction{tx})); // Locktime passes
+ BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes
BOOST_CHECK(TestSequenceLocks(CTransaction{tx})); // Sequence locks pass
tx.vin[0].nSequence = 1;
BOOST_CHECK(!TestSequenceLocks(CTransaction{tx})); // Sequence locks fail
@@ -588,7 +588,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
pblock->nNonce = bi.nonce;
}
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
- BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, nullptr));
+ BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, true, nullptr));
pblock->hashPrevBlock = pblock->GetHash();
}
diff --git a/src/test/miniscript_tests.cpp b/src/test/miniscript_tests.cpp
index 3877fea907..9387c01e73 100644
--- a/src/test/miniscript_tests.cpp
+++ b/src/test/miniscript_tests.cpp
@@ -111,11 +111,17 @@ struct KeyConverter {
assert(it != g_testdata->pkmap.end());
return it->second;
}
+
+ std::optional<std::string> ToString(const Key& key) const {
+ return HexStr(ToPKBytes(key));
+ }
};
//! Singleton instance of KeyConverter.
const KeyConverter CONVERTER{};
+// https://github.com/llvm/llvm-project/issues/53444
+// NOLINTNEXTLINE(misc-unused-using-decls)
using miniscript::operator"" _mst;
enum TestMode : int {
@@ -276,7 +282,7 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
// (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);
- BOOST_CHECK(!ms_minimalif);
+ 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);
BOOST_CHECK(ms_dup1);
@@ -290,6 +296,18 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
// 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);
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);
+ 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);
+ 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))");
// Timelock tests
Test("after(100)", "?", TESTMODE_VALID | TESTMODE_NONMAL); // only heightlock
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index dccc7ce795..ce23d6013d 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -141,23 +141,30 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
for (int i = 0; i < 4; i++)
key[i].MakeNewKey(true);
- TxoutType whichType;
+ const auto is_standard{[](const CScript& spk) {
+ TxoutType type;
+ bool res{::IsStandard(spk, std::nullopt, type)};
+ if (res) {
+ BOOST_CHECK_EQUAL(type, TxoutType::MULTISIG);
+ }
+ return res;
+ }};
CScript a_and_b;
a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK(::IsStandard(a_and_b, whichType));
+ BOOST_CHECK(is_standard(a_and_b));
CScript a_or_b;
a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK(::IsStandard(a_or_b, whichType));
+ BOOST_CHECK(is_standard(a_or_b));
CScript escrow;
escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
- BOOST_CHECK(::IsStandard(escrow, whichType));
+ BOOST_CHECK(is_standard(escrow));
CScript one_of_four;
one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG;
- BOOST_CHECK(!::IsStandard(one_of_four, whichType));
+ BOOST_CHECK(!is_standard(one_of_four));
CScript malformed[6];
malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
@@ -167,8 +174,9 @@ BOOST_AUTO_TEST_CASE(multisig_IsStandard)
malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
- for (int i = 0; i < 6; i++)
- BOOST_CHECK(!::IsStandard(malformed[i], whichType));
+ for (int i = 0; i < 6; i++) {
+ BOOST_CHECK(!is_standard(malformed[i]));
+ }
}
BOOST_AUTO_TEST_CASE(multisig_Sign)
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 115c4b9b24..12905f6b70 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -4,7 +4,7 @@
#include <chainparams.h>
#include <clientversion.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <cstdint>
#include <net.h>
#include <net_processing.h>
@@ -58,7 +58,6 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
std::string pszDest;
std::unique_ptr<CNode> pnode1 = std::make_unique<CNode>(id++,
- NODE_NETWORK,
/*sock=*/nullptr,
addr,
/*nKeyedNetGroupIn=*/0,
@@ -77,7 +76,6 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
BOOST_CHECK_EQUAL(pnode1->ConnectedThroughNetwork(), Network::NET_IPV4);
std::unique_ptr<CNode> pnode2 = std::make_unique<CNode>(id++,
- NODE_NETWORK,
/*sock=*/nullptr,
addr,
/*nKeyedNetGroupIn=*/1,
@@ -96,7 +94,6 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
BOOST_CHECK_EQUAL(pnode2->ConnectedThroughNetwork(), Network::NET_IPV4);
std::unique_ptr<CNode> pnode3 = std::make_unique<CNode>(id++,
- NODE_NETWORK,
/*sock=*/nullptr,
addr,
/*nKeyedNetGroupIn=*/0,
@@ -115,7 +112,6 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
BOOST_CHECK_EQUAL(pnode3->ConnectedThroughNetwork(), Network::NET_IPV4);
std::unique_ptr<CNode> pnode4 = std::make_unique<CNode>(id++,
- NODE_NETWORK,
/*sock=*/nullptr,
addr,
/*nKeyedNetGroupIn=*/1,
@@ -629,7 +625,6 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
ipv4AddrPeer.s_addr = 0xa0b0c001;
CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
std::unique_ptr<CNode> pnode = std::make_unique<CNode>(/*id=*/0,
- NODE_NETWORK,
/*sock=*/nullptr,
addr,
/*nKeyedNetGroupIn=*/0,
@@ -648,7 +643,7 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
pnode->SetAddrLocal(addrLocal);
// before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
- GetLocalAddrForPeer(&*pnode);
+ GetLocalAddrForPeer(*pnode);
// suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
BOOST_CHECK(1);
@@ -675,19 +670,15 @@ BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
const uint16_t bind_port = 20001;
m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));
- const uint32_t current_time = static_cast<uint32_t>(GetAdjustedTime());
- SetMockTime(current_time);
-
// Our address:port as seen from the peer, completely different from the above.
in_addr peer_us_addr;
peer_us_addr.s_addr = htonl(0x02030405);
- const CAddress peer_us{CService{peer_us_addr, 20002}, NODE_NETWORK, current_time};
+ const CService peer_us{peer_us_addr, 20002};
// Create a peer with a routable IPv4 address (outbound).
in_addr peer_out_in_addr;
peer_out_in_addr.s_addr = htonl(0x01020304);
CNode peer_out{/*id=*/0,
- /*nLocalServicesIn=*/NODE_NETWORK,
/*sock=*/nullptr,
/*addrIn=*/CAddress{CService{peer_out_in_addr, 8333}, NODE_NETWORK},
/*nKeyedNetGroupIn=*/0,
@@ -700,16 +691,15 @@ BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
peer_out.SetAddrLocal(peer_us);
// Without the fix peer_us:8333 is chosen instead of the proper peer_us:bind_port.
- auto chosen_local_addr = GetLocalAddrForPeer(&peer_out);
+ auto chosen_local_addr = GetLocalAddrForPeer(peer_out);
BOOST_REQUIRE(chosen_local_addr);
- const CAddress expected{CService{peer_us_addr, bind_port}, NODE_NETWORK, current_time};
+ const CService expected{peer_us_addr, bind_port};
BOOST_CHECK(*chosen_local_addr == expected);
// Create a peer with a routable IPv4 address (inbound).
in_addr peer_in_in_addr;
peer_in_in_addr.s_addr = htonl(0x05060708);
CNode peer_in{/*id=*/0,
- /*nLocalServicesIn=*/NODE_NETWORK,
/*sock=*/nullptr,
/*addrIn=*/CAddress{CService{peer_in_in_addr, 8333}, NODE_NETWORK},
/*nKeyedNetGroupIn=*/0,
@@ -722,7 +712,7 @@ BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
peer_in.SetAddrLocal(peer_us);
// Without the fix peer_us:8333 is chosen instead of the proper peer_us:peer_us.GetPort().
- chosen_local_addr = GetLocalAddrForPeer(&peer_in);
+ chosen_local_addr = GetLocalAddrForPeer(peer_in);
BOOST_REQUIRE(chosen_local_addr);
BOOST_CHECK(*chosen_local_addr == peer_us);
@@ -837,7 +827,6 @@ BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message)
in_addr peer_in_addr;
peer_in_addr.s_addr = htonl(0x01020304);
CNode peer{/*id=*/0,
- /*nLocalServicesIn=*/NODE_NETWORK,
/*sock=*/nullptr,
/*addrIn=*/CAddress{CService{peer_in_addr, 8333}, NODE_NETWORK},
/*nKeyedNetGroupIn=*/0,
@@ -851,13 +840,13 @@ BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message)
const int64_t time{0};
const CNetMsgMaker msg_maker{PROTOCOL_VERSION};
- // Force CChainState::IsInitialBlockDownload() to return false.
+ // Force Chainstate::IsInitialBlockDownload() to return false.
// Otherwise PushAddress() isn't called by PeerManager::ProcessMessage().
TestChainState& chainstate =
*static_cast<TestChainState*>(&m_node.chainman->ActiveChainstate());
chainstate.JumpOutOfIbd();
- m_node.peerman->InitializeNode(&peer);
+ m_node.peerman->InitializeNode(peer, NODE_NETWORK);
std::atomic<bool> interrupt_dummy{false};
std::chrono::microseconds time_received_dummy{0};
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index 224dc88d0f..c2d2fa37b4 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -480,21 +480,21 @@ BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters)
// try a few edge cases for port, service flags and time.
static const std::vector<CAddress> fixture_addresses({
- CAddress(
+ CAddress{
CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0 /* port */),
NODE_NONE,
- 0x4966bc61U /* Fri Jan 9 02:54:25 UTC 2009 */
- ),
- CAddress(
+ NodeSeconds{0x4966bc61s}, /* Fri Jan 9 02:54:25 UTC 2009 */
+ },
+ CAddress{
CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0x00f1 /* port */),
NODE_NETWORK,
- 0x83766279U /* Tue Nov 22 11:22:33 UTC 2039 */
- ),
- CAddress(
+ NodeSeconds{0x83766279s}, /* Tue Nov 22 11:22:33 UTC 2039 */
+ },
+ CAddress{
CService(CNetAddr(in6_addr(IN6ADDR_LOOPBACK_INIT)), 0xf1f2 /* port */),
static_cast<ServiceFlags>(NODE_WITNESS | NODE_COMPACT_FILTERS | NODE_NETWORK_LIMITED),
- 0xffffffffU /* Sun Feb 7 06:28:15 UTC 2106 */
- )
+ NodeSeconds{0xffffffffs}, /* Sun Feb 7 06:28:15 UTC 2106 */
+ },
});
// fixture_addresses should equal to this when serialized in V1 format.
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index 2f43ae52f7..3695ea9d16 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -20,7 +20,14 @@ BOOST_AUTO_TEST_CASE(get_next_work)
pindexLast.nHeight = 32255;
pindexLast.nTime = 1262152739; // Block #32255
pindexLast.nBits = 0x1d00ffff;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00d86aU);
+
+ // Here (and below): expected_nbits is calculated in
+ // CalculateNextWorkRequired(); redoing the calculation here would be just
+ // reimplementing the same code that is written in pow.cpp. Rather than
+ // copy that code, we just hardcode the expected result.
+ unsigned int expected_nbits = 0x1d00d86aU;
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), expected_nbits);
+ BOOST_CHECK(PermittedDifficultyTransition(chainParams->GetConsensus(), pindexLast.nHeight+1, pindexLast.nBits, expected_nbits));
}
/* Test the constraint on the upper bound for next work */
@@ -32,7 +39,9 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
pindexLast.nHeight = 2015;
pindexLast.nTime = 1233061996; // Block #2015
pindexLast.nBits = 0x1d00ffff;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00ffffU);
+ unsigned int expected_nbits = 0x1d00ffffU;
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), expected_nbits);
+ BOOST_CHECK(PermittedDifficultyTransition(chainParams->GetConsensus(), pindexLast.nHeight+1, pindexLast.nBits, expected_nbits));
}
/* Test the constraint on the lower bound for actual time taken */
@@ -44,7 +53,12 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
pindexLast.nHeight = 68543;
pindexLast.nTime = 1279297671; // Block #68543
pindexLast.nBits = 0x1c05a3f4;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1c0168fdU);
+ unsigned int expected_nbits = 0x1c0168fdU;
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), expected_nbits);
+ BOOST_CHECK(PermittedDifficultyTransition(chainParams->GetConsensus(), pindexLast.nHeight+1, pindexLast.nBits, expected_nbits));
+ // Test that reducing nbits further would not be a PermittedDifficultyTransition.
+ unsigned int invalid_nbits = expected_nbits-1;
+ BOOST_CHECK(!PermittedDifficultyTransition(chainParams->GetConsensus(), pindexLast.nHeight+1, pindexLast.nBits, invalid_nbits));
}
/* Test the constraint on the upper bound for actual time taken */
@@ -56,7 +70,12 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
pindexLast.nHeight = 46367;
pindexLast.nTime = 1269211443; // Block #46367
pindexLast.nBits = 0x1c387f6f;
- BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00e1fdU);
+ unsigned int expected_nbits = 0x1d00e1fdU;
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), expected_nbits);
+ BOOST_CHECK(PermittedDifficultyTransition(chainParams->GetConsensus(), pindexLast.nHeight+1, pindexLast.nBits, expected_nbits));
+ // Test that increasing nbits further would not be a PermittedDifficultyTransition.
+ unsigned int invalid_nbits = expected_nbits+1;
+ BOOST_CHECK(!PermittedDifficultyTransition(chainParams->GetConsensus(), pindexLast.nHeight+1, pindexLast.nBits, invalid_nbits));
}
BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_negative_target)
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp
index 9b2760fd1c..96fb28dc9f 100644
--- a/src/test/random_tests.cpp
+++ b/src/test/random_tests.cpp
@@ -53,6 +53,16 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3));
BOOST_CHECK(ctx1.rand256() == ctx2.rand256());
BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50));
+ {
+ struct MicroClock {
+ using duration = std::chrono::microseconds;
+ };
+ FastRandomContext ctx{true};
+ // Check with clock type
+ BOOST_CHECK_EQUAL(47222, ctx.rand_uniform_duration<MicroClock>(1s).count());
+ // Check with time-point type
+ BOOST_CHECK_EQUAL(2782, ctx.rand_uniform_duration<SteadySeconds>(9h).count());
+ }
// Check that a nondeterministic ones are not
g_mock_deterministic_tests = false;
diff --git a/src/test/rbf_tests.cpp b/src/test/rbf_tests.cpp
new file mode 100644
index 0000000000..c88cd36688
--- /dev/null
+++ b/src/test/rbf_tests.cpp
@@ -0,0 +1,230 @@
+// Copyright (c) 2021 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <policy/rbf.h>
+#include <random.h>
+#include <txmempool.h>
+#include <util/system.h>
+#include <util/time.h>
+
+#include <test/util/setup_common.h>
+
+#include <boost/test/unit_test.hpp>
+#include <optional>
+#include <vector>
+
+BOOST_FIXTURE_TEST_SUITE(rbf_tests, TestingSetup)
+
+static inline CTransactionRef make_tx(const std::vector<CTransactionRef>& inputs,
+ const std::vector<CAmount>& output_values)
+{
+ CMutableTransaction tx = CMutableTransaction();
+ tx.vin.resize(inputs.size());
+ tx.vout.resize(output_values.size());
+ for (size_t i = 0; i < inputs.size(); ++i) {
+ tx.vin[i].prevout.hash = inputs[i]->GetHash();
+ tx.vin[i].prevout.n = 0;
+ // Add a witness so wtxid != txid
+ CScriptWitness witness;
+ witness.stack.push_back(std::vector<unsigned char>(i + 10));
+ tx.vin[i].scriptWitness = witness;
+ }
+ for (size_t i = 0; i < output_values.size(); ++i) {
+ tx.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx.vout[i].nValue = output_values[i];
+ }
+ return MakeTransactionRef(tx);
+}
+
+static void add_descendants(const CTransactionRef& tx, int32_t num_descendants, CTxMemPool& pool)
+ EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
+{
+ AssertLockHeld(::cs_main);
+ AssertLockHeld(pool.cs);
+ TestMemPoolEntryHelper entry;
+ // Assumes this isn't already spent in mempool
+ auto tx_to_spend = tx;
+ for (int32_t i{0}; i < num_descendants; ++i) {
+ auto next_tx = make_tx(/*inputs=*/{tx_to_spend}, /*output_values=*/{(50 - i) * CENT});
+ pool.addUnchecked(entry.FromTx(next_tx));
+ tx_to_spend = next_tx;
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE(rbf_helper_functions, TestChain100Setup)
+{
+ CTxMemPool& pool = *Assert(m_node.mempool);
+ LOCK2(::cs_main, pool.cs);
+ TestMemPoolEntryHelper entry;
+
+ const CAmount low_fee{CENT/100};
+ const CAmount normal_fee{CENT/10};
+ const CAmount high_fee{CENT};
+
+ // Create a parent tx1 and child tx2 with normal fees:
+ const auto tx1 = make_tx(/*inputs=*/ {m_coinbase_txns[0]}, /*output_values=*/ {10 * COIN});
+ pool.addUnchecked(entry.Fee(normal_fee).FromTx(tx1));
+ const auto tx2 = make_tx(/*inputs=*/ {tx1}, /*output_values=*/ {995 * CENT});
+ pool.addUnchecked(entry.Fee(normal_fee).FromTx(tx2));
+
+ // Create a low-feerate parent tx3 and high-feerate child tx4 (cpfp)
+ const auto tx3 = make_tx(/*inputs=*/ {m_coinbase_txns[1]}, /*output_values=*/ {1099 * CENT});
+ pool.addUnchecked(entry.Fee(low_fee).FromTx(tx3));
+ const auto tx4 = make_tx(/*inputs=*/ {tx3}, /*output_values=*/ {999 * CENT});
+ pool.addUnchecked(entry.Fee(high_fee).FromTx(tx4));
+
+ // Create a parent tx5 and child tx6 where both have very low fees
+ const auto tx5 = make_tx(/*inputs=*/ {m_coinbase_txns[2]}, /*output_values=*/ {1099 * CENT});
+ pool.addUnchecked(entry.Fee(low_fee).FromTx(tx5));
+ const auto tx6 = make_tx(/*inputs=*/ {tx5}, /*output_values=*/ {1098 * CENT});
+ pool.addUnchecked(entry.Fee(low_fee).FromTx(tx6));
+ // Make tx6's modified fee much higher than its base fee. This should cause it to pass
+ // the fee-related checks despite being low-feerate.
+ pool.PrioritiseTransaction(tx6->GetHash(), 1 * COIN);
+
+ // Two independent high-feerate transactions, tx7 and tx8
+ const auto tx7 = make_tx(/*inputs=*/ {m_coinbase_txns[3]}, /*output_values=*/ {999 * CENT});
+ pool.addUnchecked(entry.Fee(high_fee).FromTx(tx7));
+ const auto tx8 = make_tx(/*inputs=*/ {m_coinbase_txns[4]}, /*output_values=*/ {999 * CENT});
+ pool.addUnchecked(entry.Fee(high_fee).FromTx(tx8));
+
+ const auto entry1 = pool.GetIter(tx1->GetHash()).value();
+ const auto entry2 = pool.GetIter(tx2->GetHash()).value();
+ const auto entry3 = pool.GetIter(tx3->GetHash()).value();
+ const auto entry4 = pool.GetIter(tx4->GetHash()).value();
+ const auto entry5 = pool.GetIter(tx5->GetHash()).value();
+ const auto entry6 = pool.GetIter(tx6->GetHash()).value();
+ const auto entry7 = pool.GetIter(tx7->GetHash()).value();
+ const auto entry8 = pool.GetIter(tx8->GetHash()).value();
+
+ BOOST_CHECK_EQUAL(entry1->GetFee(), normal_fee);
+ BOOST_CHECK_EQUAL(entry2->GetFee(), normal_fee);
+ BOOST_CHECK_EQUAL(entry3->GetFee(), low_fee);
+ BOOST_CHECK_EQUAL(entry4->GetFee(), high_fee);
+ BOOST_CHECK_EQUAL(entry5->GetFee(), low_fee);
+ BOOST_CHECK_EQUAL(entry6->GetFee(), low_fee);
+ BOOST_CHECK_EQUAL(entry7->GetFee(), high_fee);
+ BOOST_CHECK_EQUAL(entry8->GetFee(), high_fee);
+
+ CTxMemPool::setEntries set_12_normal{entry1, entry2};
+ CTxMemPool::setEntries set_34_cpfp{entry3, entry4};
+ CTxMemPool::setEntries set_56_low{entry5, entry6};
+ CTxMemPool::setEntries all_entries{entry1, entry2, entry3, entry4, entry5, entry6, entry7, entry8};
+ CTxMemPool::setEntries empty_set;
+
+ const auto unused_txid{GetRandHash()};
+
+ // Tests for PaysMoreThanConflicts
+ // These tests use feerate, not absolute fee.
+ BOOST_CHECK(PaysMoreThanConflicts(/*iters_conflicting=*/set_12_normal,
+ /*replacement_feerate=*/CFeeRate(entry1->GetModifiedFee() + 1, entry1->GetTxSize() + 2),
+ /*txid=*/unused_txid).has_value());
+ // Replacement must be strictly greater than the originals.
+ BOOST_CHECK(PaysMoreThanConflicts(set_12_normal, CFeeRate(entry1->GetModifiedFee(), entry1->GetTxSize()), unused_txid).has_value());
+ BOOST_CHECK(PaysMoreThanConflicts(set_12_normal, CFeeRate(entry1->GetModifiedFee() + 1, entry1->GetTxSize()), unused_txid) == std::nullopt);
+ // These tests use modified fees (including prioritisation), not base fees.
+ BOOST_CHECK(PaysMoreThanConflicts({entry5}, CFeeRate(entry5->GetModifiedFee() + 1, entry5->GetTxSize()), unused_txid) == std::nullopt);
+ BOOST_CHECK(PaysMoreThanConflicts({entry6}, CFeeRate(entry6->GetFee() + 1, entry6->GetTxSize()), unused_txid).has_value());
+ BOOST_CHECK(PaysMoreThanConflicts({entry6}, CFeeRate(entry6->GetModifiedFee() + 1, entry6->GetTxSize()), unused_txid) == std::nullopt);
+ // PaysMoreThanConflicts checks individual feerate, not ancestor feerate. This test compares
+ // replacement_feerate and entry4's feerate, which are the same. The replacement_feerate is
+ // considered too low even though entry4 has a low ancestor feerate.
+ BOOST_CHECK(PaysMoreThanConflicts(set_34_cpfp, CFeeRate(entry4->GetModifiedFee(), entry4->GetTxSize()), unused_txid).has_value());
+
+ // Tests for EntriesAndTxidsDisjoint
+ BOOST_CHECK(EntriesAndTxidsDisjoint(empty_set, {tx1->GetHash()}, unused_txid) == std::nullopt);
+ BOOST_CHECK(EntriesAndTxidsDisjoint(set_12_normal, {tx3->GetHash()}, unused_txid) == std::nullopt);
+ // EntriesAndTxidsDisjoint uses txids, not wtxids.
+ BOOST_CHECK(EntriesAndTxidsDisjoint({entry2}, {tx2->GetWitnessHash()}, unused_txid) == std::nullopt);
+ BOOST_CHECK(EntriesAndTxidsDisjoint({entry2}, {tx2->GetHash()}, unused_txid).has_value());
+ BOOST_CHECK(EntriesAndTxidsDisjoint(set_12_normal, {tx1->GetHash()}, unused_txid).has_value());
+ BOOST_CHECK(EntriesAndTxidsDisjoint(set_12_normal, {tx2->GetHash()}, unused_txid).has_value());
+ // EntriesAndTxidsDisjoint does not calculate descendants of iters_conflicting; it uses whatever
+ // the caller passed in. As such, no error is returned even though entry2 is a descendant of tx1.
+ BOOST_CHECK(EntriesAndTxidsDisjoint({entry2}, {tx1->GetHash()}, unused_txid) == std::nullopt);
+
+ // Tests for PaysForRBF
+ const CFeeRate incremental_relay_feerate{DEFAULT_INCREMENTAL_RELAY_FEE};
+ const CFeeRate higher_relay_feerate{2 * DEFAULT_INCREMENTAL_RELAY_FEE};
+ // Must pay at least as much as the original.
+ BOOST_CHECK(PaysForRBF(/*original_fees=*/high_fee,
+ /*replacement_fees=*/high_fee,
+ /*replacement_vsize=*/1,
+ /*relay_fee=*/CFeeRate(0),
+ /*txid=*/unused_txid)
+ == std::nullopt);
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee - 1, 1, CFeeRate(0), unused_txid).has_value());
+ BOOST_CHECK(PaysForRBF(high_fee + 1, high_fee, 1, CFeeRate(0), unused_txid).has_value());
+ // Additional fees must cover the replacement's vsize at incremental relay fee
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee + 1, 2, incremental_relay_feerate, unused_txid).has_value());
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee + 2, 2, incremental_relay_feerate, unused_txid) == std::nullopt);
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee + 2, 2, higher_relay_feerate, unused_txid).has_value());
+ BOOST_CHECK(PaysForRBF(high_fee, high_fee + 4, 2, higher_relay_feerate, unused_txid) == std::nullopt);
+ BOOST_CHECK(PaysForRBF(low_fee, high_fee, 99999999, incremental_relay_feerate, unused_txid).has_value());
+ BOOST_CHECK(PaysForRBF(low_fee, high_fee + 99999999, 99999999, incremental_relay_feerate, unused_txid) == std::nullopt);
+
+ // Tests for GetEntriesForConflicts
+ CTxMemPool::setEntries all_parents{entry1, entry3, entry5, entry7, entry8};
+ CTxMemPool::setEntries all_children{entry2, entry4, entry6};
+ const std::vector<CTransactionRef> parent_inputs({m_coinbase_txns[0], m_coinbase_txns[1], m_coinbase_txns[2],
+ m_coinbase_txns[3], m_coinbase_txns[4]});
+ const auto conflicts_with_parents = make_tx(parent_inputs, {50 * CENT});
+ CTxMemPool::setEntries all_conflicts;
+ BOOST_CHECK(GetEntriesForConflicts(/*tx=*/ *conflicts_with_parents.get(),
+ /*pool=*/ pool,
+ /*iters_conflicting=*/ all_parents,
+ /*all_conflicts=*/ all_conflicts) == std::nullopt);
+ BOOST_CHECK(all_conflicts == all_entries);
+ auto conflicts_size = all_conflicts.size();
+ all_conflicts.clear();
+
+ add_descendants(tx2, 23, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts) == std::nullopt);
+ conflicts_size += 23;
+ BOOST_CHECK_EQUAL(all_conflicts.size(), conflicts_size);
+ all_conflicts.clear();
+
+ add_descendants(tx4, 23, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts) == std::nullopt);
+ conflicts_size += 23;
+ BOOST_CHECK_EQUAL(all_conflicts.size(), conflicts_size);
+ all_conflicts.clear();
+
+ add_descendants(tx6, 23, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts) == std::nullopt);
+ conflicts_size += 23;
+ BOOST_CHECK_EQUAL(all_conflicts.size(), conflicts_size);
+ all_conflicts.clear();
+
+ add_descendants(tx7, 23, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts) == std::nullopt);
+ conflicts_size += 23;
+ BOOST_CHECK_EQUAL(all_conflicts.size(), conflicts_size);
+ BOOST_CHECK_EQUAL(all_conflicts.size(), 100);
+ all_conflicts.clear();
+
+ // Exceeds maximum number of conflicts.
+ add_descendants(tx8, 1, pool);
+ BOOST_CHECK(GetEntriesForConflicts(*conflicts_with_parents.get(), pool, all_parents, all_conflicts).has_value());
+
+ // Tests for HasNoNewUnconfirmed
+ const auto spends_unconfirmed = make_tx({tx1}, {36 * CENT});
+ for (const auto& input : spends_unconfirmed->vin) {
+ // Spends unconfirmed inputs.
+ BOOST_CHECK(pool.exists(GenTxid::Txid(input.prevout.hash)));
+ }
+ BOOST_CHECK(HasNoNewUnconfirmed(/*tx=*/ *spends_unconfirmed.get(),
+ /*pool=*/ pool,
+ /*iters_conflicting=*/ all_entries) == std::nullopt);
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_unconfirmed.get(), pool, {entry2}) == std::nullopt);
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_unconfirmed.get(), pool, empty_set).has_value());
+
+ const auto spends_new_unconfirmed = make_tx({tx1, tx8}, {36 * CENT});
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_new_unconfirmed.get(), pool, {entry2}).has_value());
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_new_unconfirmed.get(), pool, all_entries).has_value());
+
+ const auto spends_conflicting_confirmed = make_tx({m_coinbase_txns[0], m_coinbase_txns[1]}, {45 * CENT});
+ BOOST_CHECK(HasNoNewUnconfirmed(*spends_conflicting_confirmed.get(), pool, {entry1, entry3}) == std::nullopt);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/result_tests.cpp b/src/test/result_tests.cpp
new file mode 100644
index 0000000000..6a23a7b895
--- /dev/null
+++ b/src/test/result_tests.cpp
@@ -0,0 +1,96 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/result.h>
+
+#include <boost/test/unit_test.hpp>
+
+inline bool operator==(const bilingual_str& a, const bilingual_str& b)
+{
+ return a.original == b.original && a.translated == b.translated;
+}
+
+inline std::ostream& operator<<(std::ostream& os, const bilingual_str& s)
+{
+ return os << "bilingual_str('" << s.original << "' , '" << s.translated << "')";
+}
+
+BOOST_AUTO_TEST_SUITE(result_tests)
+
+struct NoCopy {
+ NoCopy(int n) : m_n{std::make_unique<int>(n)} {}
+ std::unique_ptr<int> m_n;
+};
+
+bool operator==(const NoCopy& a, const NoCopy& b)
+{
+ return *a.m_n == *b.m_n;
+}
+
+std::ostream& operator<<(std::ostream& os, const NoCopy& o)
+{
+ return os << "NoCopy(" << *o.m_n << ")";
+}
+
+util::Result<int> IntFn(int i, bool success)
+{
+ if (success) return i;
+ return util::Error{Untranslated(strprintf("int %i error.", i))};
+}
+
+util::Result<bilingual_str> StrFn(bilingual_str s, bool success)
+{
+ if (success) return s;
+ return util::Error{strprintf(Untranslated("str %s error."), s.original)};
+}
+
+util::Result<NoCopy> NoCopyFn(int i, bool success)
+{
+ if (success) return {i};
+ return util::Error{Untranslated(strprintf("nocopy %i error.", i))};
+}
+
+template <typename T>
+void ExpectResult(const util::Result<T>& result, bool success, const bilingual_str& str)
+{
+ BOOST_CHECK_EQUAL(bool(result), success);
+ BOOST_CHECK_EQUAL(util::ErrorString(result), str);
+}
+
+template <typename T, typename... Args>
+void ExpectSuccess(const util::Result<T>& result, const bilingual_str& str, Args&&... args)
+{
+ ExpectResult(result, true, str);
+ BOOST_CHECK_EQUAL(result.has_value(), true);
+ BOOST_CHECK_EQUAL(result.value(), T{std::forward<Args>(args)...});
+ BOOST_CHECK_EQUAL(&result.value(), &*result);
+}
+
+template <typename T, typename... Args>
+void ExpectFail(const util::Result<T>& result, const bilingual_str& str)
+{
+ ExpectResult(result, false, str);
+}
+
+BOOST_AUTO_TEST_CASE(check_returned)
+{
+ ExpectSuccess(IntFn(5, true), {}, 5);
+ ExpectFail(IntFn(5, false), Untranslated("int 5 error."));
+ ExpectSuccess(NoCopyFn(5, true), {}, 5);
+ ExpectFail(NoCopyFn(5, false), Untranslated("nocopy 5 error."));
+ ExpectSuccess(StrFn(Untranslated("S"), true), {}, Untranslated("S"));
+ ExpectFail(StrFn(Untranslated("S"), false), Untranslated("str S error."));
+}
+
+BOOST_AUTO_TEST_CASE(check_value_or)
+{
+ BOOST_CHECK_EQUAL(IntFn(10, true).value_or(20), 10);
+ BOOST_CHECK_EQUAL(IntFn(10, false).value_or(20), 20);
+ BOOST_CHECK_EQUAL(NoCopyFn(10, true).value_or(20), 10);
+ BOOST_CHECK_EQUAL(NoCopyFn(10, false).value_or(20), 20);
+ BOOST_CHECK_EQUAL(StrFn(Untranslated("A"), true).value_or(Untranslated("B")), Untranslated("A"));
+ BOOST_CHECK_EQUAL(StrFn(Untranslated("A"), false).value_or(Untranslated("B")), Untranslated("B"));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 3e9e04da25..a52530e179 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -181,10 +181,10 @@ BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
BOOST_CHECK_EQUAL(ValueFromAmount(std::numeric_limits<CAmount>::min()).write(), "-92233720368.54775808");
}
-static UniValue ValueFromString(const std::string &str)
+static UniValue ValueFromString(const std::string& str) noexcept
{
UniValue value;
- BOOST_CHECK(value.setNumStr(str));
+ value.setNumStr(str);
return value;
}
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index a221e02d2f..a02d51eecc 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -18,15 +18,18 @@
#include <boost/test/unit_test.hpp>
// Helpers:
-static std::vector<unsigned char>
-Serialize(const CScript& s)
+static bool IsStandardTx(const CTransaction& tx, std::string& reason)
+{
+ return IsStandardTx(tx, std::nullopt, DEFAULT_PERMIT_BAREMULTISIG, CFeeRate{DUST_RELAY_TX_FEE}, reason);
+}
+
+static std::vector<unsigned char> Serialize(const CScript& s)
{
std::vector<unsigned char> sSerialized(s.begin(), s.end());
return sSerialized;
}
-static bool
-Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
+static bool Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
{
// Create dummy to/from transactions:
CMutableTransaction txFrom;
@@ -49,7 +52,6 @@ BOOST_FIXTURE_TEST_SUITE(script_p2sh_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(sign)
{
- LOCK(cs_main);
// Pay-to-script-hash looks like this:
// scriptSig: <sig> <sig...> <serialized_script>
// scriptPubKey: HASH160 <hash> EQUAL
@@ -149,7 +151,6 @@ BOOST_AUTO_TEST_CASE(norecurse)
BOOST_AUTO_TEST_CASE(set)
{
- LOCK(cs_main);
// Test the CScript::Set* methods
FillableSigningProvider keystore;
CKey key[4];
@@ -263,7 +264,6 @@ BOOST_AUTO_TEST_CASE(switchover)
BOOST_AUTO_TEST_CASE(AreInputsStandard)
{
- LOCK(cs_main);
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
FillableSigningProvider keystore;
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 05bb89ab55..935194057c 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -942,7 +942,7 @@ BOOST_AUTO_TEST_CASE(script_json_test)
UniValue tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
CScriptWitness witness;
CAmount nValue = 0;
@@ -1514,8 +1514,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_returns_true)
CScriptWitness wit;
scriptPubKey << OP_1;
- CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
- CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+ CTransaction creditTx{BuildCreditingTransaction(scriptPubKey, 1)};
+ CTransaction spendTx{BuildSpendingTransaction(scriptSig, wit, creditTx)};
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << spendTx;
@@ -1537,8 +1537,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_index_err)
CScriptWitness wit;
scriptPubKey << OP_EQUAL;
- CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
- CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+ CTransaction creditTx{BuildCreditingTransaction(scriptPubKey, 1)};
+ CTransaction spendTx{BuildSpendingTransaction(scriptSig, wit, creditTx)};
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << spendTx;
@@ -1560,8 +1560,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_size)
CScriptWitness wit;
scriptPubKey << OP_EQUAL;
- CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
- CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+ CTransaction creditTx{BuildCreditingTransaction(scriptPubKey, 1)};
+ CTransaction spendTx{BuildSpendingTransaction(scriptSig, wit, creditTx)};
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << spendTx;
@@ -1583,8 +1583,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_serialization)
CScriptWitness wit;
scriptPubKey << OP_EQUAL;
- CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
- CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+ CTransaction creditTx{BuildCreditingTransaction(scriptPubKey, 1)};
+ CTransaction spendTx{BuildSpendingTransaction(scriptSig, wit, creditTx)};
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << 0xffffffff;
@@ -1606,8 +1606,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_amount_required_err)
CScriptWitness wit;
scriptPubKey << OP_EQUAL;
- CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
- CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+ CTransaction creditTx{BuildCreditingTransaction(scriptPubKey, 1)};
+ CTransaction spendTx{BuildSpendingTransaction(scriptSig, wit, creditTx)};
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << spendTx;
@@ -1629,8 +1629,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_invalid_flags)
CScriptWitness wit;
scriptPubKey << OP_EQUAL;
- CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
- CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+ CTransaction creditTx{BuildCreditingTransaction(scriptPubKey, 1)};
+ CTransaction spendTx{BuildSpendingTransaction(scriptSig, wit, creditTx)};
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << spendTx;
@@ -1813,7 +1813,7 @@ BOOST_AUTO_TEST_CASE(bip341_keypath_test_vectors)
BOOST_CHECK_EQUAL(HexStr(sighash), input["intermediary"]["sigHash"].get_str());
// To verify the sigmsg, hash the expected sigmsg, and compare it with the (expected) sighash.
- BOOST_CHECK_EQUAL(HexStr((CHashWriter(HASHER_TAPSIGHASH) << Span{ParseHex(input["intermediary"]["sigMsg"].get_str())}).GetSHA256()), input["intermediary"]["sigHash"].get_str());
+ BOOST_CHECK_EQUAL(HexStr((HashWriter{HASHER_TAPSIGHASH} << Span{ParseHex(input["intermediary"]["sigMsg"].get_str())}).GetSHA256()), input["intermediary"]["sigHash"].get_str());
}
}
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index 7376f2ff5c..514798d8fa 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -165,7 +165,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
UniValue tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
if (test.size() < 1) // Allow for extra stuff (useful for comments)
{
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
index 6dadf09176..9f5e3ab7ae 100644
--- a/src/test/skiplist_tests.cpp
+++ b/src/test/skiplist_tests.cpp
@@ -72,13 +72,13 @@ BOOST_AUTO_TEST_CASE(getlocator_test)
// Build a CChain for the main branch.
CChain chain;
- chain.SetTip(&vBlocksMain.back());
+ chain.SetTip(vBlocksMain.back());
// Test 100 random starting points for locators.
for (int n=0; n<100; n++) {
int r = InsecureRandRange(150000);
CBlockIndex* tip = (r < 100000) ? &vBlocksMain[r] : &vBlocksSide[r - 100000];
- CBlockLocator locator = chain.GetLocator(tip);
+ CBlockLocator locator = GetLocator(tip);
// The first result must be the block itself, the last one must be genesis.
BOOST_CHECK(locator.vHave.front() == tip->GetBlockHash());
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
// Build a CChain for the main branch.
CChain chain;
- chain.SetTip(&vBlocksMain.back());
+ chain.SetTip(vBlocksMain.back());
// Verify that FindEarliestAtLeast is correct.
for (unsigned int i=0; i<10000; ++i) {
@@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
}
CChain chain;
- chain.SetTip(&blocks.back());
+ chain.SetTip(blocks.back());
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50, 0)->nHeight, 0);
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100, 0)->nHeight, 0);
diff --git a/src/test/sock_tests.cpp b/src/test/sock_tests.cpp
index 9e98f4f0b1..8376ec1a68 100644
--- a/src/test/sock_tests.cpp
+++ b/src/test/sock_tests.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <compat.h>
+#include <compat/compat.h>
#include <test/util/setup_common.h>
#include <threadinterrupt.h>
#include <util/sock.h>
@@ -69,24 +69,6 @@ BOOST_AUTO_TEST_CASE(move_assignment)
BOOST_CHECK(SocketIsClosed(s));
}
-BOOST_AUTO_TEST_CASE(release)
-{
- SOCKET s = CreateSocket();
- Sock* sock = new Sock(s);
- BOOST_CHECK_EQUAL(sock->Release(), s);
- delete sock;
- BOOST_CHECK(!SocketIsClosed(s));
- BOOST_REQUIRE(CloseSocket(s));
-}
-
-BOOST_AUTO_TEST_CASE(reset)
-{
- const SOCKET s = CreateSocket();
- Sock sock(s);
- sock.Reset();
- BOOST_CHECK(SocketIsClosed(s));
-}
-
#ifndef WIN32 // Windows does not have socketpair(2).
static void CreateSocketPair(int s[2])
diff --git a/src/test/system_tests.cpp b/src/test/system_tests.cpp
index 3f5353b5a2..f160bb08a5 100644
--- a/src/test/system_tests.cpp
+++ b/src/test/system_tests.cpp
@@ -7,11 +7,6 @@
#include <univalue.h>
#ifdef ENABLE_EXTERNAL_SIGNER
-#if defined(WIN32) && !defined(__kernel_entry)
-// A workaround for boost 1.71 incompatibility with mingw-w64 compiler.
-// For details see https://github.com/bitcoin/bitcoin/pull/22348.
-#define __kernel_entry
-#endif
#if defined(__GNUC__)
// Boost 1.78 requires the following workaround.
// See: https://github.com/boostorg/process/issues/235
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 4e6c223ccc..952598f745 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -40,6 +40,9 @@ typedef std::vector<unsigned char> valtype;
// In script_tests.cpp
UniValue read_json(const std::string& jsondata);
+static CFeeRate g_dust{DUST_RELAY_TX_FEE};
+static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
+
static std::map<std::string, unsigned int> mapFlagNames = {
{std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
{std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC},
@@ -191,7 +194,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
UniValue tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
if (test[0].isArray())
{
@@ -211,7 +214,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
fValid = false;
break;
}
- UniValue vinput = input.get_array();
+ const UniValue& vinput = input.get_array();
if (vinput.size() < 3 || vinput.size() > 4)
{
fValid = false;
@@ -279,7 +282,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
UniValue tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
- UniValue test = tests[idx];
+ const UniValue& test = tests[idx];
std::string strTest = test.write();
if (test[0].isArray())
{
@@ -299,7 +302,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
fValid = false;
break;
}
- UniValue vinput = input.get_array();
+ const UniValue& vinput = input.get_array();
if (vinput.size() < 3 || vinput.size() > 4)
{
fValid = false;
@@ -745,7 +748,6 @@ BOOST_AUTO_TEST_CASE(test_witness)
BOOST_AUTO_TEST_CASE(test_IsStandard)
{
- LOCK(cs_main);
FillableSigningProvider keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
@@ -765,19 +767,19 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
constexpr auto CheckIsStandard = [](const auto& t) {
std::string reason;
- BOOST_CHECK(IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK(IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_multi, g_dust, reason));
BOOST_CHECK(reason.empty());
};
constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in) {
std::string reason;
- BOOST_CHECK(!IsStandardTx(CTransaction(t), reason));
+ BOOST_CHECK(!IsStandardTx(CTransaction{t}, MAX_OP_RETURN_RELAY, g_bare_multi, g_dust, reason));
BOOST_CHECK_EQUAL(reason_in, reason);
};
CheckIsStandard(t);
// Check dust with default relay fee:
- CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK() / 1000;
+ CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;
BOOST_CHECK_EQUAL(nDustThreshold, 546);
// dust:
t.vout[0].nValue = nDustThreshold - 1;
@@ -805,14 +807,14 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
// Check dust with odd relay fee to verify rounding:
// nDustThreshold = 182 * 3702 / 1000
- dustRelayFee = CFeeRate(3702);
+ g_dust = CFeeRate(3702);
// dust:
t.vout[0].nValue = 674 - 1;
CheckIsNotStandard(t, "dust");
// not dust:
t.vout[0].nValue = 674;
CheckIsStandard(t);
- dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
+ g_dust = CFeeRate{DUST_RELAY_TX_FEE};
t.vout[0].scriptPubKey = CScript() << OP_1;
CheckIsNotStandard(t, "scriptpubkey");
@@ -924,16 +926,16 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
CheckIsNotStandard(t, "tx-size");
- // Check bare multisig (standard if policy flag fIsBareMultisigStd is set)
- fIsBareMultisigStd = true;
+ // Check bare multisig (standard if policy flag g_bare_multi is set)
+ g_bare_multi = true;
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
t.vin.resize(1);
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
CheckIsStandard(t);
- fIsBareMultisigStd = false;
+ g_bare_multi = false;
CheckIsNotStandard(t, "bare-multisig");
- fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
+ g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;
// Check P2WPKH outputs dust threshold
t.vout[0].scriptPubKey = CScript() << OP_0 << ParseHex("ffffffffffffffffffffffffffffffffffffffff");
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
index 15213f826b..62c7ddb673 100644
--- a/src/test/txindex_tests.cpp
+++ b/src/test/txindex_tests.cpp
@@ -4,6 +4,7 @@
#include <chainparams.h>
#include <index/txindex.h>
+#include <interfaces/chain.h>
#include <script/standard.h>
#include <test/util/setup_common.h>
#include <util/time.h>
@@ -15,7 +16,7 @@ BOOST_AUTO_TEST_SUITE(txindex_tests)
BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
{
- TxIndex txindex(1 << 20, true);
+ TxIndex txindex(interfaces::MakeChain(m_node), 1 << 20, true);
CTransactionRef tx_disk;
uint256 block_hash;
@@ -28,7 +29,7 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
// BlockUntilSyncedToCurrentChain should return false before txindex is started.
BOOST_CHECK(!txindex.BlockUntilSyncedToCurrentChain());
- BOOST_REQUIRE(txindex.Start(m_node.chainman->ActiveChainstate()));
+ BOOST_REQUIRE(txindex.Start());
// Allow tx index to catch up with the block index.
constexpr int64_t timeout_ms = 10 * 1000;
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index dd4bc5af75..633f75ff4f 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -161,11 +161,6 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, Dersig100Setup)
{
// Test that passing CheckInputScripts with one set of script flags doesn't imply
// that we would pass again with a different set of flags.
- {
- LOCK(cs_main);
- InitScriptExecutionCache();
- }
-
CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
CScript p2sh_scriptPubKey = GetScriptForDestination(ScriptHash(p2pk_scriptPubKey));
CScript p2pkh_scriptPubKey = GetScriptForDestination(PKHash(coinbaseKey.GetPubKey()));
diff --git a/src/test/util/chainstate.h b/src/test/util/chainstate.h
index 5ac504c24f..2f0021b114 100644
--- a/src/test/util/chainstate.h
+++ b/src/test/util/chainstate.h
@@ -7,6 +7,7 @@
#include <clientversion.h>
#include <fs.h>
+#include <logging.h>
#include <node/context.h>
#include <node/utxo_snapshot.h>
#include <rpc/blockchain.h>
@@ -14,9 +15,7 @@
#include <univalue.h>
-#include <boost/test/unit_test.hpp>
-
-const auto NoMalleation = [](CAutoFile& file, node::SnapshotMetadata& meta){};
+const auto NoMalleation = [](AutoFile& file, node::SnapshotMetadata& meta){};
/**
* Create and activate a UTXO snapshot, optionally providing a function to
@@ -32,17 +31,17 @@ CreateAndActivateUTXOSnapshot(node::NodeContext& node, const fs::path root, F ma
WITH_LOCK(::cs_main, height = node.chainman->ActiveHeight());
fs::path snapshot_path = root / fs::u8path(tfm::format("test_snapshot.%d.dat", height));
FILE* outfile{fsbridge::fopen(snapshot_path, "wb")};
- CAutoFile auto_outfile{outfile, SER_DISK, CLIENT_VERSION};
+ AutoFile auto_outfile{outfile};
UniValue result = CreateUTXOSnapshot(
node, node.chainman->ActiveChainstate(), auto_outfile, snapshot_path, snapshot_path);
- BOOST_TEST_MESSAGE(
- "Wrote UTXO snapshot to " << fs::PathToString(snapshot_path.make_preferred()) << ": " << result.write());
+ LogPrintf(
+ "Wrote UTXO snapshot to %s: %s", fs::PathToString(snapshot_path.make_preferred()), result.write());
// Read the written snapshot in and then activate it.
//
FILE* infile{fsbridge::fopen(snapshot_path, "rb")};
- CAutoFile auto_infile{infile, SER_DISK, CLIENT_VERSION};
+ AutoFile auto_infile{infile};
node::SnapshotMetadata metadata;
auto_infile >> metadata;
diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp
index 88cf9647e7..faa0b2878c 100644
--- a/src/test/util/mining.cpp
+++ b/src/test/util/mining.cpp
@@ -68,7 +68,7 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
assert(block->nNonce);
}
- bool processed{Assert(node.chainman)->ProcessNewBlock(block, true, nullptr)};
+ bool processed{Assert(node.chainman)->ProcessNewBlock(block, true, true, nullptr)};
assert(processed);
return CTxIn{block->vtx[0]->GetHash(), 0};
diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp
index 62b770753a..21273ac5c1 100644
--- a/src/test/util/net.cpp
+++ b/src/test/util/net.cpp
@@ -5,11 +5,69 @@
#include <test/util/net.h>
#include <chainparams.h>
+#include <node/eviction.h>
#include <net.h>
+#include <net_processing.h>
+#include <netmessagemaker.h>
#include <span.h>
#include <vector>
+void ConnmanTestMsg::Handshake(CNode& node,
+ bool successfully_connected,
+ ServiceFlags remote_services,
+ ServiceFlags local_services,
+ int32_t version,
+ bool relay_txs)
+{
+ auto& peerman{static_cast<PeerManager&>(*m_msgproc)};
+ auto& connman{*this};
+ const CNetMsgMaker mm{0};
+
+ peerman.InitializeNode(node, local_services);
+
+ CSerializedNetMsg msg_version{
+ mm.Make(NetMsgType::VERSION,
+ version, //
+ Using<CustomUintFormatter<8>>(remote_services), //
+ int64_t{}, // dummy time
+ int64_t{}, // ignored service bits
+ CService{}, // dummy
+ int64_t{}, // ignored service bits
+ CService{}, // ignored
+ uint64_t{1}, // dummy nonce
+ std::string{}, // dummy subver
+ int32_t{}, // dummy starting_height
+ relay_txs),
+ };
+
+ (void)connman.ReceiveMsgFrom(node, msg_version);
+ node.fPauseSend = false;
+ connman.ProcessMessagesOnce(node);
+ {
+ LOCK(node.cs_sendProcessing);
+ peerman.SendMessages(&node);
+ }
+ if (node.fDisconnect) return;
+ assert(node.nVersion == version);
+ assert(node.GetCommonVersion() == std::min(version, PROTOCOL_VERSION));
+ CNodeStateStats statestats;
+ assert(peerman.GetNodeStateStats(node.GetId(), statestats));
+ assert(statestats.m_relay_txs == (relay_txs && !node.IsBlockOnlyConn()));
+ assert(statestats.their_services == remote_services);
+ if (successfully_connected) {
+ CSerializedNetMsg msg_verack{mm.Make(NetMsgType::VERACK)};
+ (void)connman.ReceiveMsgFrom(node, msg_verack);
+ node.fPauseSend = false;
+ connman.ProcessMessagesOnce(node);
+ {
+ LOCK(node.cs_sendProcessing);
+ peerman.SendMessages(&node);
+ }
+ assert(node.fSuccessfullyConnected == true);
+ }
+}
+
void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const
{
assert(node.ReceiveMsgBytes(msg_bytes, complete));
@@ -58,6 +116,8 @@ std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(int n_candida
/*prefer_evict=*/random_context.randbool(),
/*m_is_local=*/random_context.randbool(),
/*m_network=*/ALL_NETWORKS[random_context.randrange(ALL_NETWORKS.size())],
+ /*m_noban=*/false,
+ /*m_conn_type=*/ConnectionType::INBOUND,
});
}
return candidates;
diff --git a/src/test/util/net.h b/src/test/util/net.h
index 37d278645a..b339bee32a 100644
--- a/src/test/util/net.h
+++ b/src/test/util/net.h
@@ -5,7 +5,8 @@
#ifndef BITCOIN_TEST_UTIL_NET_H
#define BITCOIN_TEST_UTIL_NET_H
-#include <compat.h>
+#include <compat/compat.h>
+#include <node/eviction.h>
#include <netaddress.h>
#include <net.h>
#include <util/sock.h>
@@ -38,6 +39,13 @@ struct ConnmanTestMsg : public CConnman {
m_nodes.clear();
}
+ void Handshake(CNode& node,
+ bool successfully_connected,
+ ServiceFlags remote_services,
+ ServiceFlags local_services,
+ int32_t version,
+ bool relay_txs);
+
void ProcessMessagesOnce(CNode& node) { m_msgproc->ProcessMessages(&node, flagInterruptMsgProc); }
void NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const;
@@ -100,7 +108,7 @@ public:
m_socket = INVALID_SOCKET - 1;
}
- ~StaticContentsSock() override { Reset(); }
+ ~StaticContentsSock() override { m_socket = INVALID_SOCKET; }
StaticContentsSock& operator=(Sock&& other) override
{
@@ -108,11 +116,6 @@ public:
return *this;
}
- void Reset() override
- {
- m_socket = INVALID_SOCKET;
- }
-
ssize_t Send(const void*, size_t len, int) const override { return len; }
ssize_t Recv(void* buf, size_t len, int flags) const override
@@ -127,6 +130,10 @@ public:
int Connect(const sockaddr*, socklen_t) const override { return 0; }
+ int Bind(const sockaddr*, socklen_t) const override { return 0; }
+
+ int Listen(int) const override { return 0; }
+
std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override
{
if (addr != nullptr) {
@@ -152,6 +159,12 @@ public:
int SetSockOpt(int, int, const void*, socklen_t) const override { return 0; }
+ int GetSockName(sockaddr* name, socklen_t* name_len) const override
+ {
+ std::memset(name, 0x0, *name_len);
+ return 0;
+ }
+
bool Wait(std::chrono::milliseconds timeout,
Event requested,
Event* occurred = nullptr) const override
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index d9fff85bf5..74b055ee45 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -4,6 +4,8 @@
#include <test/util/setup_common.h>
+#include <kernel/validation_cache_sizes.h>
+
#include <addrman.h>
#include <banman.h>
#include <chainparams.h>
@@ -18,9 +20,13 @@
#include <net_processing.h>
#include <node/blockstorage.h>
#include <node/chainstate.h>
+#include <node/context.h>
+#include <node/mempool_args.h>
#include <node/miner.h>
+#include <node/validation_cache_args.h>
#include <noui.h>
#include <policy/fees.h>
+#include <policy/fees_args.h>
#include <pow.h>
#include <rpc/blockchain.h>
#include <rpc/register.h>
@@ -32,6 +38,7 @@
#include <test/util/net.h>
#include <timedata.h>
#include <txdb.h>
+#include <txmempool.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/thread.h>
@@ -48,13 +55,14 @@
#include <functional>
#include <stdexcept>
+using kernel::ValidationCacheSizes;
+using node::ApplyArgsManOptions;
using node::BlockAssembler;
using node::CalculateCacheSizes;
using node::LoadChainstate;
+using node::NodeContext;
using node::RegenerateCommitments;
using node::VerifyLoadedChainstate;
-using node::fPruneMode;
-using node::fReindex;
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
UrlDecodeFn* const URL_DECODE = nullptr;
@@ -100,6 +108,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
"-logsourcelocations",
"-logtimemicros",
"-logthreadnames",
+ "-loglevel=trace",
"-debug",
"-debugexclude=libevent",
"-debugexclude=leveldb",
@@ -130,8 +139,12 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
m_node.kernel = std::make_unique<kernel::Context>();
SetupEnvironment();
SetupNetworking();
- InitSignatureCache();
- InitScriptExecutionCache();
+
+ ValidationCacheSizes validation_cache_sizes{};
+ ApplyArgsManOptions(*m_node.args, validation_cache_sizes);
+ Assert(InitSignatureCache(validation_cache_sizes.signature_cache_bytes));
+ Assert(InitScriptExecutionCache(validation_cache_sizes.script_execution_cache_bytes));
+
m_node.chain = interfaces::MakeChain(m_node);
fCheckBlockIndex = true;
static bool noui_connected = false;
@@ -149,6 +162,19 @@ BasicTestingSetup::~BasicTestingSetup()
gArgs.ClearArgs();
}
+CTxMemPool::Options MemPoolOptionsForTest(const NodeContext& node)
+{
+ CTxMemPool::Options mempool_opts{
+ .estimator = node.fee_estimator.get(),
+ // Default to always checking mempool regardless of
+ // chainparams.DefaultConsistencyChecks for tests
+ .check_ratio = 1,
+ };
+ const auto err{ApplyArgsManOptions(*node.args, ::Params(), mempool_opts)};
+ Assert(!err);
+ return mempool_opts;
+}
+
ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
: BasicTestingSetup(chainName, extra_args)
{
@@ -160,14 +186,14 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
m_node.scheduler->m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { m_node.scheduler->serviceQueue(); });
GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler);
- m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
- m_node.mempool = std::make_unique<CTxMemPool>(m_node.fee_estimator.get(), m_node.args->GetIntArg("-checkmempool", 1));
+ m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(*m_node.args));
+ m_node.mempool = std::make_unique<CTxMemPool>(MemPoolOptionsForTest(m_node));
m_cache_sizes = CalculateCacheSizes(m_args);
const ChainstateManager::Options chainman_opts{
- chainparams,
- GetAdjustedTime,
+ .chainparams = chainparams,
+ .adjusted_time_callback = GetAdjustedTime,
};
m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts);
m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(m_cache_sizes.block_tree_db, true);
@@ -201,25 +227,20 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
// instead of unit tests, but for now we need these here.
RegisterAllCoreRPCCommands(tableRPC);
- auto maybe_load_error = LoadChainstate(fReindex.load(),
- *Assert(m_node.chainman.get()),
- Assert(m_node.mempool.get()),
- fPruneMode,
- m_args.GetBoolArg("-reindex-chainstate", false),
- m_cache_sizes.block_tree_db,
- m_cache_sizes.coins_db,
- m_cache_sizes.coins,
- /*block_tree_db_in_memory=*/true,
- /*coins_db_in_memory=*/true);
- assert(!maybe_load_error.has_value());
-
- auto maybe_verify_error = VerifyLoadedChainstate(
- *Assert(m_node.chainman),
- fReindex.load(),
- m_args.GetBoolArg("-reindex-chainstate", false),
- m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS),
- m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL));
- assert(!maybe_verify_error.has_value());
+ node::ChainstateLoadOptions options;
+ options.mempool = Assert(m_node.mempool.get());
+ options.block_tree_db_in_memory = true;
+ options.coins_db_in_memory = true;
+ options.reindex = node::fReindex;
+ options.reindex_chainstate = m_args.GetBoolArg("-reindex-chainstate", false);
+ options.prune = node::fPruneMode;
+ options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
+ options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
+ auto [status, error] = LoadChainstate(*Assert(m_node.chainman), m_cache_sizes, options);
+ assert(status == node::ChainstateLoadStatus::SUCCESS);
+
+ std::tie(status, error) = VerifyLoadedChainstate(*Assert(m_node.chainman), options);
+ assert(status == node::ChainstateLoadStatus::SUCCESS);
BlockValidationState state;
if (!m_node.chainman->ActiveChainstate().ActivateBestChain(state)) {
@@ -275,7 +296,7 @@ void TestChain100Setup::mineBlocks(int num_blocks)
CBlock TestChain100Setup::CreateBlock(
const std::vector<CMutableTransaction>& txns,
const CScript& scriptPubKey,
- CChainState& chainstate)
+ Chainstate& chainstate)
{
CBlock block = BlockAssembler{chainstate, nullptr}.CreateNewBlock(scriptPubKey)->block;
@@ -293,7 +314,7 @@ CBlock TestChain100Setup::CreateBlock(
CBlock TestChain100Setup::CreateAndProcessBlock(
const std::vector<CMutableTransaction>& txns,
const CScript& scriptPubKey,
- CChainState* chainstate)
+ Chainstate* chainstate)
{
if (!chainstate) {
chainstate = &Assert(m_node.chainman)->ActiveChainstate();
@@ -301,7 +322,7 @@ CBlock TestChain100Setup::CreateAndProcessBlock(
const CBlock block = this->CreateBlock(txns, scriptPubKey, *chainstate);
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
- Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, nullptr);
+ Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, true, nullptr);
return block;
}
diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h
index 37407bcb92..136ee1fd62 100644
--- a/src/test/util/setup_common.h
+++ b/src/test/util/setup_common.h
@@ -90,6 +90,9 @@ struct BasicTestingSetup {
ArgsManager m_args;
};
+
+CTxMemPool::Options MemPoolOptionsForTest(const node::NodeContext& node);
+
/** Testing setup that performs all steps up until right before
* ChainstateManager gets initialized. Meant for testing ChainstateManager
* initialization behaviour.
@@ -131,7 +134,7 @@ struct TestChain100Setup : public TestingSetup {
*/
CBlock CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns,
const CScript& scriptPubKey,
- CChainState* chainstate = nullptr);
+ Chainstate* chainstate = nullptr);
/**
* Create a new block with just given transactions, coinbase paying to
@@ -140,7 +143,7 @@ struct TestChain100Setup : public TestingSetup {
CBlock CreateBlock(
const std::vector<CMutableTransaction>& txns,
const CScript& scriptPubKey,
- CChainState& chainstate);
+ Chainstate& chainstate);
//! Mine a series of new blocks on the active chain.
void mineBlocks(int num_blocks);
diff --git a/src/test/util/validation.h b/src/test/util/validation.h
index b0bc717b6c..cbe7745b81 100644
--- a/src/test/util/validation.h
+++ b/src/test/util/validation.h
@@ -9,7 +9,7 @@
class CValidationInterface;
-struct TestChainState : public CChainState {
+struct TestChainState : public Chainstate {
/** Reset the ibd cache to its initial state */
void ResetIbd();
/** Toggle IsInitialBlockDownload from true to false */
diff --git a/src/test/util/wallet.cpp b/src/test/util/wallet.cpp
index 52aaeabccf..b54774cbb9 100644
--- a/src/test/util/wallet.cpp
+++ b/src/test/util/wallet.cpp
@@ -8,6 +8,7 @@
#include <outputtype.h>
#include <script/standard.h>
#ifdef ENABLE_WALLET
+#include <util/check.h>
#include <util/translation.h>
#include <wallet/wallet.h>
#endif
@@ -20,11 +21,7 @@ const std::string ADDRESS_BCRT1_UNSPENDABLE = "bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqq
std::string getnewaddress(CWallet& w)
{
constexpr auto output_type = OutputType::BECH32;
- CTxDestination dest;
- bilingual_str error;
- if (!w.GetNewDestination(output_type, "", dest, error)) assert(false);
-
- return EncodeDestination(dest);
+ return EncodeDestination(*Assert(w.GetNewDestination(output_type, "")));
}
#endif // ENABLE_WALLET
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index fda56ccff7..0f9f332dc6 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -23,6 +23,7 @@
#include <util/string.h>
#include <util/time.h>
#include <util/vector.h>
+#include <util/bitdeque.h>
#include <array>
#include <fstream>
@@ -238,15 +239,31 @@ BOOST_AUTO_TEST_CASE(span_write_bytes)
BOOST_AUTO_TEST_CASE(util_Join)
{
// Normal version
- BOOST_CHECK_EQUAL(Join({}, ", "), "");
- BOOST_CHECK_EQUAL(Join({"foo"}, ", "), "foo");
- BOOST_CHECK_EQUAL(Join({"foo", "bar"}, ", "), "foo, bar");
+ BOOST_CHECK_EQUAL(Join(std::vector<std::string>{}, ", "), "");
+ BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo"}, ", "), "foo");
+ BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo", "bar"}, ", "), "foo, bar");
// Version with unary operator
const auto op_upper = [](const std::string& s) { return ToUpper(s); };
- BOOST_CHECK_EQUAL(Join<std::string>({}, ", ", op_upper), "");
- BOOST_CHECK_EQUAL(Join<std::string>({"foo"}, ", ", op_upper), "FOO");
- BOOST_CHECK_EQUAL(Join<std::string>({"foo", "bar"}, ", ", op_upper), "FOO, BAR");
+ BOOST_CHECK_EQUAL(Join(std::list<std::string>{}, ", ", op_upper), "");
+ BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo"}, ", ", op_upper), "FOO");
+ BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo", "bar"}, ", ", op_upper), "FOO, BAR");
+}
+
+BOOST_AUTO_TEST_CASE(util_ReplaceAll)
+{
+ const std::string original("A test \"%s\" string '%s'.");
+ auto test_replaceall = [&original](const std::string& search, const std::string& substitute, const std::string& expected) {
+ auto test = original;
+ ReplaceAll(test, search, substitute);
+ BOOST_CHECK_EQUAL(test, expected);
+ };
+
+ test_replaceall("", "foo", original);
+ test_replaceall(original, "foo", "foo");
+ test_replaceall("%s", "foo", "A test \"foo\" string 'foo'.");
+ test_replaceall("\"", "foo", "A test foo%sfoo string '%s'.");
+ test_replaceall("'", "foo", "A test \"%s\" string foo%sfoo.");
}
BOOST_AUTO_TEST_CASE(util_TrimString)
@@ -2494,13 +2511,13 @@ BOOST_AUTO_TEST_CASE(test_tracked_vector)
auto v2 = Vector(std::move(t2));
BOOST_CHECK_EQUAL(v2.size(), 1U);
- BOOST_CHECK(v2[0].origin == &t2);
+ BOOST_CHECK(v2[0].origin == &t2); // NOLINT(*-use-after-move)
BOOST_CHECK_EQUAL(v2[0].copies, 0);
auto v3 = Vector(t1, std::move(t2));
BOOST_CHECK_EQUAL(v3.size(), 2U);
BOOST_CHECK(v3[0].origin == &t1);
- BOOST_CHECK(v3[1].origin == &t2);
+ BOOST_CHECK(v3[1].origin == &t2); // NOLINT(*-use-after-move)
BOOST_CHECK_EQUAL(v3[0].copies, 1);
BOOST_CHECK_EQUAL(v3[1].copies, 0);
@@ -2508,7 +2525,7 @@ BOOST_AUTO_TEST_CASE(test_tracked_vector)
BOOST_CHECK_EQUAL(v4.size(), 3U);
BOOST_CHECK(v4[0].origin == &t1);
BOOST_CHECK(v4[1].origin == &t2);
- BOOST_CHECK(v4[2].origin == &t3);
+ BOOST_CHECK(v4[2].origin == &t3); // NOLINT(*-use-after-move)
BOOST_CHECK_EQUAL(v4[0].copies, 1);
BOOST_CHECK_EQUAL(v4[1].copies, 1);
BOOST_CHECK_EQUAL(v4[2].copies, 0);
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index 7ade4d8195..bb1ade153a 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -100,7 +100,7 @@ std::shared_ptr<CBlock> MinerTestingSetup::FinalizeBlock(std::shared_ptr<CBlock>
// submit block header, so that miner can get the block height from the
// global state and the node has the topology of the chain
BlockValidationState ignored;
- BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({pblock->GetBlockHeader()}, ignored));
+ BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({pblock->GetBlockHeader()}, true, ignored));
return pblock;
}
@@ -157,7 +157,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
bool ignored;
// Connect the genesis block and drain any outstanding events
- BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored));
+ BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(std::make_shared<CBlock>(Params().GenesisBlock()), true, true, &ignored));
SyncWithValidationInterfaceQueue();
// subscribe to events (this subscriber will validate event ordering)
@@ -179,13 +179,13 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
FastRandomContext insecure;
for (int i = 0; i < 1000; i++) {
auto block = blocks[insecure.randrange(blocks.size() - 1)];
- Assert(m_node.chainman)->ProcessNewBlock(block, true, &ignored);
+ Assert(m_node.chainman)->ProcessNewBlock(block, true, true, &ignored);
}
// to make sure that eventually we process the full chain - do it here
- for (auto block : blocks) {
+ for (const auto& block : blocks) {
if (block->vtx.size() == 1) {
- bool processed = Assert(m_node.chainman)->ProcessNewBlock(block, true, &ignored);
+ bool processed = Assert(m_node.chainman)->ProcessNewBlock(block, true, true, &ignored);
assert(processed);
}
}
@@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
{
bool ignored;
auto ProcessBlock = [&](std::shared_ptr<const CBlock> block) -> bool {
- return Assert(m_node.chainman)->ProcessNewBlock(block, /*force_processing=*/true, /*new_block=*/&ignored);
+ return Assert(m_node.chainman)->ProcessNewBlock(block, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&ignored);
};
// Process all mined blocks
@@ -234,7 +234,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
// Run the test multiple times
for (int test_runs = 3; test_runs > 0; --test_runs) {
- BOOST_CHECK_EQUAL(last_mined->GetHash(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
+ BOOST_CHECK_EQUAL(last_mined->GetHash(), WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockHash()));
// Later on split from here
const uint256 split_hash{last_mined->hashPrevBlock};
@@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
ProcessBlock(b);
}
// Check that the reorg was eventually successful
- BOOST_CHECK_EQUAL(last_mined->GetHash(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
+ BOOST_CHECK_EQUAL(last_mined->GetHash(), WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockHash()));
// We can join the other thread, which returns when the reorg was successful
rpc_thread.join();
@@ -325,6 +325,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
BOOST_AUTO_TEST_CASE(witness_commitment_index)
{
+ LOCK(Assert(m_node.chainman)->GetMutex());
CScript pubKey;
pubKey << 1 << OP_TRUE;
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get()}.CreateNewBlock(pubKey);
diff --git a/src/test/validation_chainstate_tests.cpp b/src/test/validation_chainstate_tests.cpp
index 102de74389..347a967b33 100644
--- a/src/test/validation_chainstate_tests.cpp
+++ b/src/test/validation_chainstate_tests.cpp
@@ -9,7 +9,6 @@
#include <sync.h>
#include <test/util/chainstate.h>
#include <test/util/setup_common.h>
-#include <timedata.h>
#include <uint256.h>
#include <validation.h>
@@ -17,19 +16,13 @@
#include <boost/test/unit_test.hpp>
-BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, ChainTestingSetup)
-//! Test resizing coins-related CChainState caches during runtime.
+//! Test resizing coins-related Chainstate caches during runtime.
//!
BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
{
- const ChainstateManager::Options chainman_opts{
- Params(),
- GetAdjustedTime,
- };
- ChainstateManager manager{chainman_opts};
-
- WITH_LOCK(::cs_main, manager.m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(1 << 20, true));
+ ChainstateManager& manager = *Assert(m_node.chainman);
CTxMemPool& mempool = *Assert(m_node.mempool);
//! Create and add a Coin with DynamicMemoryUsage of 80 bytes to the given view.
@@ -45,7 +38,7 @@ BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
return outp;
};
- CChainState& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
+ Chainstate& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
c1.InitCoinsDB(
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
@@ -113,8 +106,8 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
BOOST_CHECK_EQUAL(chainman.GetAll().size(), 2);
- CChainState& background_cs{*[&] {
- for (CChainState* cs : chainman.GetAll()) {
+ Chainstate& background_cs{*[&] {
+ for (Chainstate* cs : chainman.GetAll()) {
if (cs != &chainman.ActiveChainstate()) {
return cs;
}
@@ -139,7 +132,7 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
bool checked = CheckBlock(*pblock, state, chainparams.GetConsensus());
BOOST_CHECK(checked);
bool accepted = background_cs.AcceptBlock(
- pblock, state, &pindex, true, nullptr, &newblock);
+ pblock, state, &pindex, true, nullptr, &newblock, true);
BOOST_CHECK(accepted);
}
// UpdateTip is called here
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
index 6dc522b421..24ad9458c9 100644
--- a/src/test/validation_chainstatemanager_tests.cpp
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -32,13 +32,13 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
ChainstateManager& manager = *m_node.chainman;
CTxMemPool& mempool = *m_node.mempool;
- std::vector<CChainState*> chainstates;
+ std::vector<Chainstate*> chainstates;
BOOST_CHECK(!manager.SnapshotBlockhash().has_value());
// Create a legacy (IBD) chainstate.
//
- CChainState& c1 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(&mempool));
+ Chainstate& c1 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(&mempool));
chainstates.push_back(&c1);
c1.InitCoinsDB(
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
@@ -49,12 +49,12 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
auto all = manager.GetAll();
BOOST_CHECK_EQUAL_COLLECTIONS(all.begin(), all.end(), chainstates.begin(), chainstates.end());
- auto& active_chain = manager.ActiveChain();
+ auto& active_chain = WITH_LOCK(manager.GetMutex(), return manager.ActiveChain());
BOOST_CHECK_EQUAL(&active_chain, &c1.m_chain);
- BOOST_CHECK_EQUAL(manager.ActiveHeight(), -1);
+ BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), -1);
- auto active_tip = manager.ActiveTip();
+ auto active_tip = WITH_LOCK(manager.GetMutex(), return manager.ActiveTip());
auto exp_tip = c1.m_chain.Tip();
BOOST_CHECK_EQUAL(active_tip, exp_tip);
@@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
// Create a snapshot-based chainstate.
//
const uint256 snapshot_blockhash = GetRandHash();
- CChainState& c2 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(
+ Chainstate& c2 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(
&mempool, snapshot_blockhash));
chainstates.push_back(&c2);
@@ -84,12 +84,12 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
auto all2 = manager.GetAll();
BOOST_CHECK_EQUAL_COLLECTIONS(all2.begin(), all2.end(), chainstates.begin(), chainstates.end());
- auto& active_chain2 = manager.ActiveChain();
+ auto& active_chain2 = WITH_LOCK(manager.GetMutex(), return manager.ActiveChain());
BOOST_CHECK_EQUAL(&active_chain2, &c2.m_chain);
- BOOST_CHECK_EQUAL(manager.ActiveHeight(), 0);
+ BOOST_CHECK_EQUAL(WITH_LOCK(manager.GetMutex(), return manager.ActiveHeight()), 0);
- auto active_tip2 = manager.ActiveTip();
+ auto active_tip2 = WITH_LOCK(manager.GetMutex(), return manager.ActiveTip());
auto exp_tip2 = c2.m_chain.Tip();
BOOST_CHECK_EQUAL(active_tip2, exp_tip2);
@@ -111,11 +111,11 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
manager.m_total_coinsdb_cache = max_cache;
manager.m_total_coinstip_cache = max_cache;
- std::vector<CChainState*> chainstates;
+ std::vector<Chainstate*> chainstates;
// Create a legacy (IBD) chainstate.
//
- CChainState& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
+ Chainstate& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
chainstates.push_back(&c1);
c1.InitCoinsDB(
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
@@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
// Create a snapshot-based chainstate.
//
- CChainState& c2 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool, GetRandHash()));
+ Chainstate& c2 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool, GetRandHash()));
chainstates.push_back(&c2);
c2.InitCoinsDB(
/*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
@@ -193,7 +193,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup)
// Should not load malleated snapshots
BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
- m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
+ m_node, m_path_root, [](AutoFile& auto_infile, SnapshotMetadata& metadata) {
// A UTXO is missing but count is correct
metadata.m_coins_count -= 1;
@@ -204,22 +204,22 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup)
auto_infile >> coin;
}));
BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
- m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
+ m_node, m_path_root, [](AutoFile& auto_infile, SnapshotMetadata& metadata) {
// Coins count is larger than coins in file
metadata.m_coins_count += 1;
}));
BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
- m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
+ m_node, m_path_root, [](AutoFile& auto_infile, SnapshotMetadata& metadata) {
// Coins count is smaller than coins in file
metadata.m_coins_count -= 1;
}));
BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
- m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
+ m_node, m_path_root, [](AutoFile& auto_infile, SnapshotMetadata& metadata) {
// Wrong hash
metadata.m_base_blockhash = uint256::ZERO;
}));
BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
- m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
+ m_node, m_path_root, [](AutoFile& auto_infile, SnapshotMetadata& metadata) {
// Wrong hash
metadata.m_base_blockhash = uint256::ONE;
}));
@@ -236,7 +236,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup)
BOOST_CHECK(WITH_LOCK(::cs_main, return !chainman.ActiveChain().Genesis()->IsAssumedValid()));
const AssumeutxoData& au_data = *ExpectedAssumeutxo(snapshot_height, ::Params());
- const CBlockIndex* tip = chainman.ActiveTip();
+ const CBlockIndex* tip = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip());
BOOST_CHECK_EQUAL(tip->nChainTx, au_data.nChainTx);
@@ -250,7 +250,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup)
LOCK(::cs_main);
int chains_tested{0};
- for (CChainState* chainstate : chainman.GetAll()) {
+ for (Chainstate* chainstate : chainman.GetAll()) {
BOOST_TEST_MESSAGE("Checking coins in " << chainstate->ToString());
CCoinsViewCache& coinscache = chainstate->CoinsTip();
@@ -283,7 +283,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup)
size_t coins_in_background{0};
size_t coins_missing_from_background{0};
- for (CChainState* chainstate : chainman.GetAll()) {
+ for (Chainstate* chainstate : chainman.GetAll()) {
BOOST_TEST_MESSAGE("Checking coins in " << chainstate->ToString());
CCoinsViewCache& coinscache = chainstate->CoinsTip();
bool is_background = chainstate != &chainman.ActiveChainstate();
@@ -326,7 +326,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
{
ChainstateManager& chainman = *Assert(m_node.chainman);
CTxMemPool& mempool = *m_node.mempool;
- CChainState& cs1 = chainman.ActiveChainstate();
+ Chainstate& cs1 = chainman.ActiveChainstate();
int num_indexes{0};
int num_assumed_valid{0};
@@ -335,10 +335,10 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid;
CBlockIndex* validated_tip{nullptr};
- CBlockIndex* assumed_tip{chainman.ActiveChain().Tip()};
+ CBlockIndex* assumed_tip{WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip())};
auto reload_all_block_indexes = [&]() {
- for (CChainState* cs : chainman.GetAll()) {
+ for (Chainstate* cs : chainman.GetAll()) {
LOCK(::cs_main);
cs->UnloadBlockIndex();
BOOST_CHECK(cs->setBlockIndexCandidates.empty());
@@ -373,7 +373,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
BOOST_CHECK_EQUAL(expected_assumed_valid, num_assumed_valid);
- CChainState& cs2 = WITH_LOCK(::cs_main,
+ Chainstate& cs2 = WITH_LOCK(::cs_main,
return chainman.InitializeChainstate(&mempool, GetRandHash()));
reload_all_block_indexes();
diff --git a/src/test/validation_flush_tests.cpp b/src/test/validation_flush_tests.cpp
index 012169b17e..c06e6c8d3b 100644
--- a/src/test/validation_flush_tests.cpp
+++ b/src/test/validation_flush_tests.cpp
@@ -4,27 +4,20 @@
//
#include <sync.h>
#include <test/util/setup_common.h>
-#include <txmempool.h>
#include <validation.h>
#include <boost/test/unit_test.hpp>
-using node::BlockManager;
-
-BOOST_FIXTURE_TEST_SUITE(validation_flush_tests, ChainTestingSetup)
+BOOST_FIXTURE_TEST_SUITE(validation_flush_tests, TestingSetup)
//! Test utilities for detecting when we need to flush the coins cache based
//! on estimated memory usage.
//!
-//! @sa CChainState::GetCoinsCacheSizeState()
+//! @sa Chainstate::GetCoinsCacheSizeState()
//!
BOOST_AUTO_TEST_CASE(getcoinscachesizestate)
{
- CTxMemPool& mempool = *Assert(m_node.mempool);
- BlockManager blockman{};
- CChainState chainstate{&mempool, blockman, *Assert(m_node.chainman)};
- chainstate.InitCoinsDB(/*cache_size_bytes=*/1 << 10, /*in_memory=*/true, /*should_wipe=*/false);
- WITH_LOCK(::cs_main, chainstate.InitCoinsCache(1 << 10));
+ Chainstate& chainstate{m_node.chainman->ActiveChainstate()};
constexpr bool is_64_bit = sizeof(void*) == 8;
diff --git a/src/threadinterrupt.cpp b/src/threadinterrupt.cpp
index 340106ed99..e28b447c1d 100644
--- a/src/threadinterrupt.cpp
+++ b/src/threadinterrupt.cpp
@@ -28,18 +28,8 @@ void CThreadInterrupt::operator()()
cond.notify_all();
}
-bool CThreadInterrupt::sleep_for(std::chrono::milliseconds rel_time)
+bool CThreadInterrupt::sleep_for(Clock::duration rel_time)
{
WAIT_LOCK(mut, lock);
return !cond.wait_for(lock, rel_time, [this]() { return flag.load(std::memory_order_acquire); });
}
-
-bool CThreadInterrupt::sleep_for(std::chrono::seconds rel_time)
-{
- return sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(rel_time));
-}
-
-bool CThreadInterrupt::sleep_for(std::chrono::minutes rel_time)
-{
- return sleep_for(std::chrono::duration_cast<std::chrono::milliseconds>(rel_time));
-}
diff --git a/src/threadinterrupt.h b/src/threadinterrupt.h
index 992016b4f6..979bc2ee3e 100644
--- a/src/threadinterrupt.h
+++ b/src/threadinterrupt.h
@@ -6,6 +6,7 @@
#define BITCOIN_THREADINTERRUPT_H
#include <sync.h>
+#include <threadsafety.h>
#include <atomic>
#include <chrono>
@@ -19,13 +20,12 @@
class CThreadInterrupt
{
public:
+ using Clock = std::chrono::steady_clock;
CThreadInterrupt();
explicit operator bool() const;
void operator()() EXCLUSIVE_LOCKS_REQUIRED(!mut);
void reset();
- bool sleep_for(std::chrono::milliseconds rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut);
- bool sleep_for(std::chrono::seconds rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut);
- bool sleep_for(std::chrono::minutes rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut);
+ bool sleep_for(Clock::duration rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut);
private:
std::condition_variable cond;
diff --git a/src/timedata.cpp b/src/timedata.cpp
index ceee08e68c..fe9a5fbed7 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -32,9 +32,9 @@ int64_t GetTimeOffset()
return nTimeOffset;
}
-int64_t GetAdjustedTime()
+NodeClock::time_point GetAdjustedTime()
{
- return GetTime() + GetTimeOffset();
+ return NodeClock::now() + std::chrono::seconds{GetTimeOffset()};
}
#define BITCOIN_TIMEDATA_MAX_SAMPLES 200
diff --git a/src/timedata.h b/src/timedata.h
index 2f039d5465..669a571f47 100644
--- a/src/timedata.h
+++ b/src/timedata.h
@@ -5,9 +5,12 @@
#ifndef BITCOIN_TIMEDATA_H
#define BITCOIN_TIMEDATA_H
+#include <util/time.h>
+
#include <algorithm>
-#include <assert.h>
-#include <stdint.h>
+#include <cassert>
+#include <chrono>
+#include <cstdint>
#include <vector>
static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT = 70 * 60;
@@ -72,7 +75,7 @@ public:
/** Functions to keep track of adjusted P2P time */
int64_t GetTimeOffset();
-int64_t GetAdjustedTime();
+NodeClock::time_point GetAdjustedTime();
void AddTimeData(const CNetAddr& ip, int64_t nTime);
/**
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index d6e792a55f..3a21a79a34 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -7,7 +7,7 @@
#include <chainparams.h>
#include <chainparamsbase.h>
-#include <compat.h>
+#include <compat/compat.h>
#include <crypto/hmac_sha256.h>
#include <net.h>
#include <netaddress.h>
diff --git a/src/txdb.cpp b/src/txdb.cpp
index a0939873ad..bad3bb80a9 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -211,7 +211,6 @@ public:
bool GetKey(COutPoint &key) const override;
bool GetValue(Coin &coin) const override;
- unsigned int GetValueSize() const override;
bool Valid() const override;
void Next() override;
@@ -257,11 +256,6 @@ bool CCoinsViewDBCursor::GetValue(Coin &coin) const
return pcursor->GetValue(coin);
}
-unsigned int CCoinsViewDBCursor::GetValueSize() const
-{
- return pcursor->GetValueSize();
-}
-
bool CCoinsViewDBCursor::Valid() const
{
return keyTmp.first == DB_COIN;
@@ -316,7 +310,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams,
CDiskBlockIndex diskindex;
if (pcursor->GetValue(diskindex)) {
// Construct block index object
- CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash());
+ CBlockIndex* pindexNew = insertBlockIndex(diskindex.ConstructBlockHash());
pindexNew->pprev = insertBlockIndex(diskindex.hashPrev);
pindexNew->nHeight = diskindex.nHeight;
pindexNew->nFile = diskindex.nFile;
diff --git a/src/txdb.h b/src/txdb.h
index faa543b412..a04596f7bb 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -8,6 +8,7 @@
#include <coins.h>
#include <dbwrapper.h>
+#include <sync.h>
#include <memory>
#include <optional>
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 65c8b4ea60..e1288b7346 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -14,7 +14,9 @@
#include <policy/policy.h>
#include <policy/settings.h>
#include <reverse_iterator.h>
+#include <util/check.h>
#include <util/moneystr.h>
+#include <util/overflow.h>
#include <util/system.h>
#include <util/time.h>
#include <validationinterface.h>
@@ -22,38 +24,6 @@
#include <cmath>
#include <optional>
-// Helpers for modifying CTxMemPool::mapTx, which is a boost multi_index.
-struct update_descendant_state
-{
- update_descendant_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount) :
- modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount)
- {}
-
- void operator() (CTxMemPoolEntry &e)
- { e.UpdateDescendantState(modifySize, modifyFee, modifyCount); }
-
- private:
- int64_t modifySize;
- CAmount modifyFee;
- int64_t modifyCount;
-};
-
-struct update_ancestor_state
-{
- update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int64_t _modifySigOpsCost) :
- modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOpsCost(_modifySigOpsCost)
- {}
-
- void operator() (CTxMemPoolEntry &e)
- { e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOpsCost); }
-
- private:
- int64_t modifySize;
- CAmount modifyFee;
- int64_t modifyCount;
- int64_t modifySigOpsCost;
-};
-
bool TestLockPointValidity(CChain& active_chain, const LockPoints& lp)
{
AssertLockHeld(cs_main);
@@ -82,6 +52,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
entryHeight{entry_height},
spendsCoinbase{spends_coinbase},
sigOpCost{sigops_cost},
+ m_modified_fee{nFee},
lockPoints{lp},
nSizeWithDescendants{GetTxSize()},
nModFeesWithDescendants{nFee},
@@ -89,11 +60,11 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& tx, CAmount fee,
nModFeesWithAncestors{nFee},
nSigOpCostWithAncestors{sigOpCost} {}
-void CTxMemPoolEntry::UpdateFeeDelta(CAmount newFeeDelta)
+void CTxMemPoolEntry::UpdateModifiedFee(CAmount fee_diff)
{
- nModFeesWithDescendants += newFeeDelta - feeDelta;
- nModFeesWithAncestors += newFeeDelta - feeDelta;
- feeDelta = newFeeDelta;
+ nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, fee_diff);
+ nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, fee_diff);
+ m_modified_fee = SaturatingAdd(m_modified_fee, fee_diff);
}
void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
@@ -103,12 +74,11 @@ void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
size_t CTxMemPoolEntry::GetTxSize() const
{
- return GetVirtualTransactionSize(nTxWeight, sigOpCost);
+ return GetVirtualTransactionSize(nTxWeight, sigOpCost, ::nBytesPerSigOp);
}
void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendants,
- const std::set<uint256>& setExclude, std::set<uint256>& descendants_to_remove,
- uint64_t ancestor_size_limit, uint64_t ancestor_count_limit)
+ const std::set<uint256>& setExclude, std::set<uint256>& descendants_to_remove)
{
CTxMemPoolEntry::Children stageEntries, descendants;
stageEntries = updateIt->GetMemPoolChildrenConst();
@@ -144,19 +114,21 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendan
modifyCount++;
cachedDescendants[updateIt].insert(mapTx.iterator_to(descendant));
// Update ancestor state for each descendant
- mapTx.modify(mapTx.iterator_to(descendant), update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost()));
+ mapTx.modify(mapTx.iterator_to(descendant), [=](CTxMemPoolEntry& e) {
+ e.UpdateAncestorState(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost());
+ });
// Don't directly remove the transaction here -- doing so would
// invalidate iterators in cachedDescendants. Mark it for removal
// by inserting into descendants_to_remove.
- if (descendant.GetCountWithAncestors() > ancestor_count_limit || descendant.GetSizeWithAncestors() > ancestor_size_limit) {
+ if (descendant.GetCountWithAncestors() > uint64_t(m_limits.ancestor_count) || descendant.GetSizeWithAncestors() > uint64_t(m_limits.ancestor_size_vbytes)) {
descendants_to_remove.insert(descendant.GetTx().GetHash());
}
}
}
- mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
+ mapTx.modify(updateIt, [=](CTxMemPoolEntry& e) { e.UpdateDescendantState(modifySize, modifyFee, modifyCount); });
}
-void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate, uint64_t ancestor_size_limit, uint64_t ancestor_count_limit)
+void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256>& vHashesToUpdate)
{
AssertLockHeld(cs);
// For each entry in vHashesToUpdate, store the set of in-mempool, but not
@@ -199,7 +171,7 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashes
}
}
} // release epoch guard for UpdateForDescendants
- UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded, descendants_to_remove, ancestor_size_limit, ancestor_count_limit);
+ UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded, descendants_to_remove);
}
for (const auto& txid : descendants_to_remove) {
@@ -345,7 +317,7 @@ void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors
const int64_t updateSize = updateCount * it->GetTxSize();
const CAmount updateFee = updateCount * it->GetModifiedFee();
for (txiter ancestorIt : setAncestors) {
- mapTx.modify(ancestorIt, update_descendant_state(updateSize, updateFee, updateCount));
+ mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e) { e.UpdateDescendantState(updateSize, updateFee, updateCount); });
}
}
@@ -360,7 +332,7 @@ void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncesto
updateFee += ancestorIt->GetModifiedFee();
updateSigOpsCost += ancestorIt->GetSigOpCost();
}
- mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOpsCost));
+ mapTx.modify(it, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(updateSize, updateFee, updateCount, updateSigOpsCost); });
}
void CTxMemPool::UpdateChildrenForRemoval(txiter it)
@@ -391,7 +363,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
CAmount modifyFee = -removeIt->GetModifiedFee();
int modifySigOps = -removeIt->GetSigOpCost();
for (txiter dit : setDescendants) {
- mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps));
+ mapTx.modify(dit, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(modifySize, modifyFee, -1, modifySigOps); });
}
}
}
@@ -435,7 +407,7 @@ void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFe
{
nSizeWithDescendants += modifySize;
assert(int64_t(nSizeWithDescendants) > 0);
- nModFeesWithDescendants += modifyFee;
+ nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, modifyFee);
nCountWithDescendants += modifyCount;
assert(int64_t(nCountWithDescendants) > 0);
}
@@ -444,15 +416,26 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee,
{
nSizeWithAncestors += modifySize;
assert(int64_t(nSizeWithAncestors) > 0);
- nModFeesWithAncestors += modifyFee;
+ nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, modifyFee);
nCountWithAncestors += modifyCount;
assert(int64_t(nCountWithAncestors) > 0);
nSigOpCostWithAncestors += modifySigOps;
assert(int(nSigOpCostWithAncestors) >= 0);
}
-CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator, int check_ratio)
- : m_check_ratio(check_ratio), minerPolicyEstimator(estimator)
+CTxMemPool::CTxMemPool(const Options& opts)
+ : m_check_ratio{opts.check_ratio},
+ minerPolicyEstimator{opts.estimator},
+ m_max_size_bytes{opts.max_size_bytes},
+ m_expiry{opts.expiry},
+ m_incremental_relay_feerate{opts.incremental_relay_feerate},
+ m_min_relay_feerate{opts.min_relay_feerate},
+ m_dust_relay_feerate{opts.dust_relay_feerate},
+ m_permit_bare_multisig{opts.permit_bare_multisig},
+ m_max_datacarrier_bytes{opts.max_datacarrier_bytes},
+ m_require_standard{opts.require_standard},
+ m_full_rbf{opts.full_rbf},
+ m_limits{opts.limits}
{
_clear(); //lock free clear
}
@@ -483,8 +466,10 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
// Update transaction for any feeDelta created by PrioritiseTransaction
CAmount delta{0};
ApplyDelta(entry.GetTx().GetHash(), delta);
+ // The following call to UpdateModifiedFee assumes no previous fee modifications
+ Assume(entry.GetFee() == entry.GetModifiedFee());
if (delta) {
- mapTx.modify(newit, [&delta](CTxMemPoolEntry& e) { e.UpdateFeeDelta(delta); });
+ mapTx.modify(newit, [&delta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(delta); });
}
// Update cachedInnerUsage to include contained transaction's usage.
@@ -917,24 +902,24 @@ void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeD
{
LOCK(cs);
CAmount &delta = mapDeltas[hash];
- delta += nFeeDelta;
+ delta = SaturatingAdd(delta, nFeeDelta);
txiter it = mapTx.find(hash);
if (it != mapTx.end()) {
- mapTx.modify(it, [&delta](CTxMemPoolEntry& e) { e.UpdateFeeDelta(delta); });
+ mapTx.modify(it, [&nFeeDelta](CTxMemPoolEntry& e) { e.UpdateModifiedFee(nFeeDelta); });
// Now update all ancestors' modified fees with descendants
setEntries setAncestors;
uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
std::string dummy;
CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
for (txiter ancestorIt : setAncestors) {
- mapTx.modify(ancestorIt, update_descendant_state(0, nFeeDelta, 0));
+ mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e){ e.UpdateDescendantState(0, nFeeDelta, 0);});
}
// Now update all descendants' modified fees with ancestors
setEntries setDescendants;
CalculateDescendants(it, setDescendants);
setDescendants.erase(it);
for (txiter descendantIt : setDescendants) {
- mapTx.modify(descendantIt, update_ancestor_state(0, nFeeDelta, 0, 0));
+ mapTx.modify(descendantIt, [=](CTxMemPoolEntry& e){ e.UpdateAncestorState(0, nFeeDelta, 0, 0); });
}
++nTransactionsUpdated;
}
@@ -1108,12 +1093,12 @@ CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
lastRollingFeeUpdate = time;
- if (rollingMinimumFeeRate < (double)incrementalRelayFee.GetFeePerK() / 2) {
+ if (rollingMinimumFeeRate < (double)m_incremental_relay_feerate.GetFeePerK() / 2) {
rollingMinimumFeeRate = 0;
return CFeeRate(0);
}
}
- return std::max(CFeeRate(llround(rollingMinimumFeeRate)), incrementalRelayFee);
+ return std::max(CFeeRate(llround(rollingMinimumFeeRate)), m_incremental_relay_feerate);
}
void CTxMemPool::trackPackageRemoved(const CFeeRate& rate) {
@@ -1137,7 +1122,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpends
// to have 0 fee). This way, we don't allow txn to enter mempool with feerate
// equal to txn which were removed with no block in between.
CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
- removed += incrementalRelayFee;
+ removed += m_incremental_relay_feerate;
trackPackageRemoved(removed);
maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
@@ -1201,14 +1186,14 @@ void CTxMemPool::GetTransactionAncestry(const uint256& txid, size_t& ancestors,
}
}
-bool CTxMemPool::IsLoaded() const
+bool CTxMemPool::GetLoadTried() const
{
LOCK(cs);
- return m_is_loaded;
+ return m_load_tried;
}
-void CTxMemPool::SetIsLoaded(bool loaded)
+void CTxMemPool::SetLoadTried(bool load_tried)
{
LOCK(cs);
- m_is_loaded = loaded;
+ m_load_tried = load_tried;
}
diff --git a/src/txmempool.h b/src/txmempool.h
index f5d5abc62e..cd15d069b1 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -14,6 +14,9 @@
#include <utility>
#include <vector>
+#include <kernel/mempool_limits.h>
+#include <kernel/mempool_options.h>
+
#include <coins.h>
#include <consensus/amount.h>
#include <indirectmap.h>
@@ -32,7 +35,7 @@
class CBlockIndex;
class CChain;
-class CChainState;
+class Chainstate;
extern RecursiveMutex cs_main;
/** Fake height value used in Coin to signify they are only in the memory pool (since 0.8) */
@@ -101,7 +104,7 @@ private:
const unsigned int entryHeight; //!< Chain height when entering the mempool
const bool spendsCoinbase; //!< keep track of transactions that spend a coinbase
const int64_t sigOpCost; //!< Total sigop cost
- CAmount feeDelta{0}; //!< Used for determining the priority of the transaction for mining in a block
+ CAmount m_modified_fee; //!< Used for determining the priority of the transaction for mining in a block
LockPoints lockPoints; //!< Track the height and time at which tx was final
// Information about descendants of this transaction that are in the
@@ -131,7 +134,7 @@ public:
std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; }
unsigned int GetHeight() const { return entryHeight; }
int64_t GetSigOpCost() const { return sigOpCost; }
- CAmount GetModifiedFee() const { return nFee + feeDelta; }
+ CAmount GetModifiedFee() const { return m_modified_fee; }
size_t DynamicMemoryUsage() const { return nUsageSize; }
const LockPoints& GetLockPoints() const { return lockPoints; }
@@ -139,9 +142,8 @@ public:
void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
// Adjusts the ancestor state
void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps);
- // Updates the fee delta used for mining priority score, and the
- // modified fees with descendants/ancestors.
- void UpdateFeeDelta(CAmount newFeeDelta);
+ // Updates the modified fees with descendants/ancestors.
+ void UpdateModifiedFee(CAmount fee_diff);
// Update the LockPoints after a reorg
void UpdateLockPoints(const LockPoints& lp);
@@ -363,7 +365,7 @@ enum class MemPoolRemovalReason {
* - a transaction which doesn't meet the minimum fee requirements.
* - a new transaction that double-spends an input of a transaction already in
* the pool where the new transaction does not meet the Replace-By-Fee
- * requirements as defined in BIP 125.
+ * requirements as defined in doc/policy/mempool-replacements.md.
* - a non-standard transaction.
*
* CTxMemPool::mapTx, and CTxMemPoolEntry bookkeeping:
@@ -449,7 +451,9 @@ protected:
void trackPackageRemoved(const CFeeRate& rate) EXCLUSIVE_LOCKS_REQUIRED(cs);
- bool m_is_loaded GUARDED_BY(cs){false};
+ bool m_load_tried GUARDED_BY(cs){false};
+
+ CFeeRate GetMinFee(size_t sizelimit) const;
public:
@@ -560,15 +564,28 @@ public:
indirectmap<COutPoint, const CTransaction*> mapNextTx GUARDED_BY(cs);
std::map<uint256, CAmount> mapDeltas GUARDED_BY(cs);
+ using Options = kernel::MemPoolOptions;
+
+ const int64_t m_max_size_bytes;
+ const std::chrono::seconds m_expiry;
+ const CFeeRate m_incremental_relay_feerate;
+ const CFeeRate m_min_relay_feerate;
+ const CFeeRate m_dust_relay_feerate;
+ const bool m_permit_bare_multisig;
+ const std::optional<unsigned> m_max_datacarrier_bytes;
+ const bool m_require_standard;
+ const bool m_full_rbf;
+
+ using Limits = kernel::MemPoolLimits;
+
+ const Limits m_limits;
+
/** Create a new CTxMemPool.
* Sanity checks will be off by default for performance, because otherwise
* accepting transactions becomes O(N^2) where N is the number of transactions
* in the pool.
- *
- * @param[in] estimator is used to estimate appropriate transaction fees.
- * @param[in] check_ratio is the ratio used to determine how often sanity checks will run.
*/
- explicit CTxMemPool(CBlockPolicyEstimator* estimator = nullptr, int check_ratio = 0);
+ explicit CTxMemPool(const Options& opts);
/**
* If sanity-checking is turned on, check makes sure the pool is
@@ -648,13 +665,8 @@ public:
*
* @param[in] vHashesToUpdate The set of txids from the
* disconnected block that have been accepted back into the mempool.
- * @param[in] ancestor_size_limit The maximum allowed size in virtual
- * bytes of an entry and its ancestors
- * @param[in] ancestor_count_limit The maximum allowed number of
- * transactions including the entry and its ancestors.
*/
- void UpdateTransactionsFromBlock(const std::vector<uint256>& vHashesToUpdate,
- uint64_t ancestor_size_limit, uint64_t ancestor_count_limit) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main) LOCKS_EXCLUDED(m_epoch);
+ void UpdateTransactionsFromBlock(const std::vector<uint256>& vHashesToUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main) LOCKS_EXCLUDED(m_epoch);
/** Try to calculate all in-mempool ancestors of entry.
* (these are all calculated including the tx itself)
@@ -696,12 +708,14 @@ public:
void CalculateDescendants(txiter it, setEntries& setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs);
/** The minimum fee to get into the mempool, which may itself not be enough
- * for larger-sized transactions.
- * The incrementalRelayFee policy variable is used to bound the time it
- * takes the fee rate to go back down all the way to 0. When the feerate
- * would otherwise be half of this, it is set to 0 instead.
- */
- CFeeRate GetMinFee(size_t sizelimit) const;
+ * for larger-sized transactions.
+ * The m_incremental_relay_feerate policy variable is used to bound the time it
+ * takes the fee rate to go back down all the way to 0. When the feerate
+ * would otherwise be half of this, it is set to 0 instead.
+ */
+ CFeeRate GetMinFee() const {
+ return GetMinFee(m_max_size_bytes);
+ }
/** Remove transactions from the mempool until its dynamic size is <= sizelimit.
* pvNoSpendsRemaining, if set, will be populated with the list of outpoints
@@ -720,11 +734,17 @@ public:
*/
void GetTransactionAncestry(const uint256& txid, size_t& ancestors, size_t& descendants, size_t* ancestorsize = nullptr, CAmount* ancestorfees = nullptr) const;
- /** @returns true if the mempool is fully loaded */
- bool IsLoaded() const;
+ /**
+ * @returns true if we've made an attempt to load the mempool regardless of
+ * whether the attempt was successful or not
+ */
+ bool GetLoadTried() const;
- /** Sets the current loaded state */
- void SetIsLoaded(bool loaded);
+ /**
+ * Set whether or not we've made an attempt to load the mempool (regardless
+ * of whether the attempt was successful or not)
+ */
+ void SetLoadTried(bool load_tried);
unsigned long size() const
{
@@ -827,14 +847,9 @@ private:
* @param[out] descendants_to_remove Populated with the txids of entries that
* exceed ancestor limits. It's the responsibility of the caller to
* removeRecursive them.
- * @param[in] ancestor_size_limit the max number of ancestral bytes allowed
- * for any descendant
- * @param[in] ancestor_count_limit the max number of ancestor transactions
- * allowed for any descendant
*/
void UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendants,
- const std::set<uint256>& setExclude, std::set<uint256>& descendants_to_remove,
- uint64_t ancestor_size_limit, uint64_t ancestor_count_limit) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ const std::set<uint256>& setExclude, std::set<uint256>& descendants_to_remove) EXCLUSIVE_LOCKS_REQUIRED(cs);
/** Update ancestors of hash to add/remove it as a descendant transaction. */
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs);
/** Set ancestor state for an entry */
diff --git a/src/txorphanage.cpp b/src/txorphanage.cpp
index ed4783f1a5..69ae8ea582 100644
--- a/src/txorphanage.cpp
+++ b/src/txorphanage.cpp
@@ -102,7 +102,7 @@ void TxOrphanage::EraseForPeer(NodeId peer)
if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx from peer=%d\n", nErased, peer);
}
-unsigned int TxOrphanage::LimitOrphans(unsigned int max_orphans)
+void TxOrphanage::LimitOrphans(unsigned int max_orphans)
{
AssertLockHeld(g_cs_orphans);
@@ -135,7 +135,7 @@ unsigned int TxOrphanage::LimitOrphans(unsigned int max_orphans)
EraseTx(m_orphan_list[randompos]->first);
++nEvicted;
}
- return nEvicted;
+ if (nEvicted > 0) LogPrint(BCLog::MEMPOOL, "orphanage overflow, removed %u tx\n", nEvicted);
}
void TxOrphanage::AddChildrenToWorkSet(const CTransaction& tx, std::set<uint256>& orphan_work_set) const
diff --git a/src/txorphanage.h b/src/txorphanage.h
index 24c8318f36..9363e6f733 100644
--- a/src/txorphanage.h
+++ b/src/txorphanage.h
@@ -41,7 +41,7 @@ public:
void EraseForBlock(const CBlock& block) LOCKS_EXCLUDED(::g_cs_orphans);
/** Limit the orphanage to the given maximum */
- unsigned int LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
+ void LimitOrphans(unsigned int max_orphans) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans);
/** Add any orphans that list a particular tx as a parent into a peer's work set
* (ie orphans that may have found their final missing parent, and so should be reconsidered for the mempool) */
diff --git a/src/uint256.h b/src/uint256.h
index 5c3a2f5409..e74b9ff7b1 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -6,6 +6,7 @@
#ifndef BITCOIN_UINT256_H
#define BITCOIN_UINT256_H
+#include <crypto/common.h>
#include <span.h>
#include <assert.h>
@@ -84,15 +85,7 @@ public:
uint64_t GetUint64(int pos) const
{
- const uint8_t* ptr = m_data + pos * 8;
- return ((uint64_t)ptr[0]) | \
- ((uint64_t)ptr[1]) << 8 | \
- ((uint64_t)ptr[2]) << 16 | \
- ((uint64_t)ptr[3]) << 24 | \
- ((uint64_t)ptr[4]) << 32 | \
- ((uint64_t)ptr[5]) << 40 | \
- ((uint64_t)ptr[6]) << 48 | \
- ((uint64_t)ptr[7]) << 56;
+ return ReadLE64(m_data + pos * 8);
}
template<typename Stream>
diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h
index 22be0311e8..ccaf56a271 100644
--- a/src/univalue/include/univalue.h
+++ b/src/univalue/include/univalue.h
@@ -24,41 +24,39 @@ public:
typ = initialType;
val = initialStr;
}
- UniValue(uint64_t val_) {
- setInt(val_);
- }
- UniValue(int64_t val_) {
- setInt(val_);
- }
- UniValue(bool val_) {
- setBool(val_);
- }
- UniValue(int val_) {
- setInt(val_);
- }
- UniValue(double val_) {
- setFloat(val_);
- }
- UniValue(const std::string& val_) {
- setStr(val_);
- }
- UniValue(const char *val_) {
- std::string s(val_);
- setStr(s);
+ template <typename Ref, typename T = std::remove_cv_t<std::remove_reference_t<Ref>>,
+ std::enable_if_t<std::is_floating_point_v<T> || // setFloat
+ std::is_same_v<bool, T> || // setBool
+ std::is_signed_v<T> || std::is_unsigned_v<T> || // setInt
+ std::is_constructible_v<std::string, T>, // setStr
+ bool> = true>
+ UniValue(Ref&& val)
+ {
+ if constexpr (std::is_floating_point_v<T>) {
+ setFloat(val);
+ } else if constexpr (std::is_same_v<bool, T>) {
+ setBool(val);
+ } else if constexpr (std::is_signed_v<T>) {
+ setInt(int64_t{val});
+ } else if constexpr (std::is_unsigned_v<T>) {
+ setInt(uint64_t{val});
+ } else {
+ setStr(std::string{std::forward<Ref>(val)});
+ }
}
void clear();
- bool setNull();
- bool setBool(bool val);
- bool setNumStr(const std::string& val);
- bool setInt(uint64_t val);
- bool setInt(int64_t val);
- bool setInt(int val_) { return setInt((int64_t)val_); }
- bool setFloat(double val);
- bool setStr(const std::string& val);
- bool setArray();
- bool setObject();
+ void setNull();
+ void setBool(bool val);
+ void setNumStr(const std::string& val);
+ void setInt(uint64_t val);
+ void setInt(int64_t val);
+ void setInt(int val_) { return setInt(int64_t{val_}); }
+ void setFloat(double val);
+ void setStr(const std::string& val);
+ void setArray();
+ void setObject();
enum VType getType() const { return typ; }
const std::string& getValStr() const { return val; }
@@ -82,12 +80,14 @@ public:
bool isArray() const { return (typ == VARR); }
bool isObject() const { return (typ == VOBJ); }
- bool push_back(const UniValue& val);
- bool push_backV(const std::vector<UniValue>& vec);
+ void push_back(UniValue val);
+ void push_backV(const std::vector<UniValue>& vec);
+ template <class It>
+ void push_backV(It first, It last);
- void __pushKV(const std::string& key, const UniValue& val);
- bool pushKV(const std::string& key, const UniValue& val);
- bool pushKVs(const UniValue& obj);
+ void __pushKV(std::string key, UniValue val);
+ void pushKV(std::string key, UniValue val);
+ void pushKVs(UniValue obj);
std::string write(unsigned int prettyIndent = 0,
unsigned int indentLevel = 0) const;
@@ -104,6 +104,7 @@ private:
std::vector<std::string> keys;
std::vector<UniValue> values;
+ void checkType(const VType& expected) const;
bool findKey(const std::string& key, size_t& retIdx) const;
void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
@@ -114,19 +115,7 @@ public:
const std::vector<std::string>& getKeys() const;
const std::vector<UniValue>& getValues() const;
template <typename Int>
- auto getInt() const
- {
- static_assert(std::is_integral<Int>::value);
- if (typ != VNUM) {
- throw std::runtime_error("JSON value is not an integer as expected");
- }
- Int result;
- const auto [first_nonmatching, error_condition] = std::from_chars(val.data(), val.data() + val.size(), result);
- if (first_nonmatching != val.data() + val.size() || error_condition != std::errc{}) {
- throw std::runtime_error("JSON integer out of range");
- }
- return result;
- }
+ Int getInt() const;
bool get_bool() const;
const std::string& get_str() const;
double get_real() const;
@@ -137,6 +126,26 @@ public:
friend const UniValue& find_value( const UniValue& obj, const std::string& name);
};
+template <class It>
+void UniValue::push_backV(It first, It last)
+{
+ checkType(VARR);
+ values.insert(values.end(), first, last);
+}
+
+template <typename Int>
+Int UniValue::getInt() const
+{
+ static_assert(std::is_integral<Int>::value);
+ checkType(VNUM);
+ Int result;
+ const auto [first_nonmatching, error_condition] = std::from_chars(val.data(), val.data() + val.size(), result);
+ if (first_nonmatching != val.data() + val.size() || error_condition != std::errc{}) {
+ throw std::runtime_error("JSON integer out of range");
+ }
+ return result;
+}
+
enum jtokentype {
JTOK_ERR = -1,
JTOK_NONE = 0, // eof
diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp
index 3553995c28..12a434dd0e 100644
--- a/src/univalue/lib/univalue.cpp
+++ b/src/univalue/lib/univalue.cpp
@@ -23,19 +23,17 @@ void UniValue::clear()
values.clear();
}
-bool UniValue::setNull()
+void UniValue::setNull()
{
clear();
- return true;
}
-bool UniValue::setBool(bool val_)
+void UniValue::setBool(bool val_)
{
clear();
typ = VBOOL;
if (val_)
val = "1";
- return true;
}
static bool validNumStr(const std::string& s)
@@ -46,18 +44,18 @@ static bool validNumStr(const std::string& s)
return (tt == JTOK_NUMBER);
}
-bool UniValue::setNumStr(const std::string& val_)
+void UniValue::setNumStr(const std::string& val_)
{
- if (!validNumStr(val_))
- return false;
+ if (!validNumStr(val_)) {
+ throw std::runtime_error{"The string '" + val_ + "' is not a valid JSON number"};
+ }
clear();
typ = VNUM;
val = val_;
- return true;
}
-bool UniValue::setInt(uint64_t val_)
+void UniValue::setInt(uint64_t val_)
{
std::ostringstream oss;
@@ -66,7 +64,7 @@ bool UniValue::setInt(uint64_t val_)
return setNumStr(oss.str());
}
-bool UniValue::setInt(int64_t val_)
+void UniValue::setInt(int64_t val_)
{
std::ostringstream oss;
@@ -75,86 +73,74 @@ bool UniValue::setInt(int64_t val_)
return setNumStr(oss.str());
}
-bool UniValue::setFloat(double val_)
+void UniValue::setFloat(double val_)
{
std::ostringstream oss;
oss << std::setprecision(16) << val_;
- bool ret = setNumStr(oss.str());
- typ = VNUM;
- return ret;
+ return setNumStr(oss.str());
}
-bool UniValue::setStr(const std::string& val_)
+void UniValue::setStr(const std::string& val_)
{
clear();
typ = VSTR;
val = val_;
- return true;
}
-bool UniValue::setArray()
+void UniValue::setArray()
{
clear();
typ = VARR;
- return true;
}
-bool UniValue::setObject()
+void UniValue::setObject()
{
clear();
typ = VOBJ;
- return true;
}
-bool UniValue::push_back(const UniValue& val_)
+void UniValue::push_back(UniValue val)
{
- if (typ != VARR)
- return false;
+ checkType(VARR);
- values.push_back(val_);
- return true;
+ values.push_back(std::move(val));
}
-bool UniValue::push_backV(const std::vector<UniValue>& vec)
+void UniValue::push_backV(const std::vector<UniValue>& vec)
{
- if (typ != VARR)
- return false;
+ checkType(VARR);
values.insert(values.end(), vec.begin(), vec.end());
-
- return true;
}
-void UniValue::__pushKV(const std::string& key, const UniValue& val_)
+void UniValue::__pushKV(std::string key, UniValue val)
{
- keys.push_back(key);
- values.push_back(val_);
+ checkType(VOBJ);
+
+ keys.push_back(std::move(key));
+ values.push_back(std::move(val));
}
-bool UniValue::pushKV(const std::string& key, const UniValue& val_)
+void UniValue::pushKV(std::string key, UniValue val)
{
- if (typ != VOBJ)
- return false;
+ checkType(VOBJ);
size_t idx;
if (findKey(key, idx))
- values[idx] = val_;
+ values[idx] = std::move(val);
else
- __pushKV(key, val_);
- return true;
+ __pushKV(std::move(key), std::move(val));
}
-bool UniValue::pushKVs(const UniValue& obj)
+void UniValue::pushKVs(UniValue obj)
{
- if (typ != VOBJ || obj.typ != VOBJ)
- return false;
+ checkType(VOBJ);
+ obj.checkType(VOBJ);
for (size_t i = 0; i < obj.keys.size(); i++)
- __pushKV(obj.keys[i], obj.values.at(i));
-
- return true;
+ __pushKV(std::move(obj.keys.at(i)), std::move(obj.values.at(i)));
}
void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const
@@ -221,6 +207,14 @@ const UniValue& UniValue::operator[](size_t index) const
return values.at(index);
}
+void UniValue::checkType(const VType& expected) const
+{
+ if (typ != expected) {
+ throw std::runtime_error{"JSON value of type " + std::string{uvTypeName(typ)} + " is not of expected type " +
+ std::string{uvTypeName(expected)}};
+ }
+}
+
const char *uvTypeName(UniValue::VType t)
{
switch (t) {
diff --git a/src/univalue/lib/univalue_get.cpp b/src/univalue/lib/univalue_get.cpp
index 9bbdb1fe69..5c58f388dd 100644
--- a/src/univalue/lib/univalue_get.cpp
+++ b/src/univalue/lib/univalue_get.cpp
@@ -46,8 +46,7 @@ bool ParseDouble(const std::string& str, double *out)
const std::vector<std::string>& UniValue::getKeys() const
{
- if (typ != VOBJ)
- throw std::runtime_error("JSON value is not an object as expected");
+ checkType(VOBJ);
return keys;
}
@@ -60,22 +59,19 @@ const std::vector<UniValue>& UniValue::getValues() const
bool UniValue::get_bool() const
{
- if (typ != VBOOL)
- throw std::runtime_error("JSON value is not a boolean as expected");
+ checkType(VBOOL);
return getBool();
}
const std::string& UniValue::get_str() const
{
- if (typ != VSTR)
- throw std::runtime_error("JSON value is not a string as expected");
+ checkType(VSTR);
return getValStr();
}
double UniValue::get_real() const
{
- if (typ != VNUM)
- throw std::runtime_error("JSON value is not a number as expected");
+ checkType(VNUM);
double retval;
if (!ParseDouble(getValStr(), &retval))
throw std::runtime_error("JSON double out of range");
@@ -84,15 +80,12 @@ double UniValue::get_real() const
const UniValue& UniValue::get_obj() const
{
- if (typ != VOBJ)
- throw std::runtime_error("JSON value is not an object as expected");
+ checkType(VOBJ);
return *this;
}
const UniValue& UniValue::get_array() const
{
- if (typ != VARR)
- throw std::runtime_error("JSON value is not an array as expected");
+ checkType(VARR);
return *this;
}
-
diff --git a/src/univalue/sources.mk b/src/univalue/sources.mk
index e156216378..5e4d9c3831 100644
--- a/src/univalue/sources.mk
+++ b/src/univalue/sources.mk
@@ -1,12 +1,8 @@
-# - All variables are namespaced with UNIVALUE_ to avoid colliding with
-# downstream makefiles.
# - All Variables ending in _HEADERS or _SOURCES confuse automake, so the
# _INT postfix is applied.
# - Convenience variables, for example a UNIVALUE_TEST_DIR should not be used
# as they interfere with automatic dependency generation
-# - The %reldir% is the relative path from the Makefile.am. This allows
-# downstreams to use these variables without having to manually account for
-# the path change.
+# - The %reldir% is the relative path from the Makefile.am.
UNIVALUE_INCLUDE_DIR_INT = %reldir%/include
@@ -29,9 +25,6 @@ UNIVALUE_TEST_UNITESTER_INT += %reldir%/test/unitester.cpp
UNIVALUE_TEST_JSON_INT =
UNIVALUE_TEST_JSON_INT += %reldir%/test/test_json.cpp
-UNIVALUE_TEST_NO_NUL_INT =
-UNIVALUE_TEST_NO_NUL_INT += %reldir%/test/no_nul.cpp
-
UNIVALUE_TEST_OBJECT_INT =
UNIVALUE_TEST_OBJECT_INT += %reldir%/test/object.cpp
diff --git a/src/univalue/test/.gitignore b/src/univalue/test/.gitignore
index 7b27cf0da2..5812c96b14 100644
--- a/src/univalue/test/.gitignore
+++ b/src/univalue/test/.gitignore
@@ -2,7 +2,6 @@
object
unitester
test_json
-no_nul
*.trs
*.log
diff --git a/src/univalue/test/no_nul.cpp b/src/univalue/test/no_nul.cpp
deleted file mode 100644
index 3a7a727abb..0000000000
--- a/src/univalue/test/no_nul.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <univalue.h>
-
-int main (int argc, char *argv[])
-{
- char buf[] = "___[1,2,3]___";
- UniValue val;
- return val.read(buf + 3, 7) ? 0 : 1;
-}
diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp
index 8a35bf914d..94d7343ff3 100644
--- a/src/univalue/test/object.cpp
+++ b/src/univalue/test/object.cpp
@@ -13,9 +13,6 @@
#include <string>
#include <vector>
-#define BOOST_FIXTURE_TEST_SUITE(a, b)
-#define BOOST_AUTO_TEST_CASE(funcName) void funcName()
-#define BOOST_AUTO_TEST_SUITE_END()
#define BOOST_CHECK(expr) assert(expr)
#define BOOST_CHECK_EQUAL(v1, v2) assert((v1) == (v2))
#define BOOST_CHECK_THROW(stmt, excMatch) { \
@@ -35,9 +32,7 @@
} \
}
-BOOST_FIXTURE_TEST_SUITE(univalue_tests, BasicTestingSetup)
-
-BOOST_AUTO_TEST_CASE(univalue_constructor)
+void univalue_constructor()
{
UniValue v1;
BOOST_CHECK(v1.isNull());
@@ -50,7 +45,7 @@ BOOST_AUTO_TEST_CASE(univalue_constructor)
BOOST_CHECK_EQUAL(v3.getValStr(), "foo");
UniValue numTest;
- BOOST_CHECK(numTest.setNumStr("82"));
+ numTest.setNumStr("82");
BOOST_CHECK(numTest.isNum());
BOOST_CHECK_EQUAL(numTest.getValStr(), "82");
@@ -85,36 +80,46 @@ BOOST_AUTO_TEST_CASE(univalue_constructor)
BOOST_CHECK_EQUAL(v9.getValStr(), "zappa");
}
-BOOST_AUTO_TEST_CASE(univalue_typecheck)
+void univalue_push_throw()
+{
+ UniValue j;
+ BOOST_CHECK_THROW(j.push_back(1), std::runtime_error);
+ BOOST_CHECK_THROW(j.push_backV({1}), std::runtime_error);
+ BOOST_CHECK_THROW(j.__pushKV("k", 1), std::runtime_error);
+ BOOST_CHECK_THROW(j.pushKV("k", 1), std::runtime_error);
+ BOOST_CHECK_THROW(j.pushKVs({}), std::runtime_error);
+}
+
+void univalue_typecheck()
{
UniValue v1;
- BOOST_CHECK(v1.setNumStr("1"));
+ v1.setNumStr("1");
BOOST_CHECK(v1.isNum());
BOOST_CHECK_THROW(v1.get_bool(), std::runtime_error);
{
UniValue v_negative;
- BOOST_CHECK(v_negative.setNumStr("-1"));
+ v_negative.setNumStr("-1");
BOOST_CHECK_THROW(v_negative.getInt<uint8_t>(), std::runtime_error);
BOOST_CHECK_EQUAL(v_negative.getInt<int8_t>(), -1);
}
UniValue v2;
- BOOST_CHECK(v2.setBool(true));
+ v2.setBool(true);
BOOST_CHECK_EQUAL(v2.get_bool(), true);
BOOST_CHECK_THROW(v2.getInt<int>(), std::runtime_error);
UniValue v3;
- BOOST_CHECK(v3.setNumStr("32482348723847471234"));
+ v3.setNumStr("32482348723847471234");
BOOST_CHECK_THROW(v3.getInt<int64_t>(), std::runtime_error);
- BOOST_CHECK(v3.setNumStr("1000"));
+ v3.setNumStr("1000");
BOOST_CHECK_EQUAL(v3.getInt<int64_t>(), 1000);
UniValue v4;
- BOOST_CHECK(v4.setNumStr("2147483648"));
+ v4.setNumStr("2147483648");
BOOST_CHECK_EQUAL(v4.getInt<int64_t>(), 2147483648);
BOOST_CHECK_THROW(v4.getInt<int>(), std::runtime_error);
- BOOST_CHECK(v4.setNumStr("1000"));
+ v4.setNumStr("1000");
BOOST_CHECK_EQUAL(v4.getInt<int>(), 1000);
BOOST_CHECK_THROW(v4.get_str(), std::runtime_error);
BOOST_CHECK_EQUAL(v4.get_real(), 1000);
@@ -134,77 +139,77 @@ BOOST_AUTO_TEST_CASE(univalue_typecheck)
BOOST_CHECK_THROW(vals[1].get_bool(), std::runtime_error);
}
-BOOST_AUTO_TEST_CASE(univalue_set)
+void univalue_set()
{
UniValue v(UniValue::VSTR, "foo");
v.clear();
BOOST_CHECK(v.isNull());
BOOST_CHECK_EQUAL(v.getValStr(), "");
- BOOST_CHECK(v.setObject());
+ v.setObject();
BOOST_CHECK(v.isObject());
BOOST_CHECK_EQUAL(v.size(), 0);
BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ);
BOOST_CHECK(v.empty());
- BOOST_CHECK(v.setArray());
+ v.setArray();
BOOST_CHECK(v.isArray());
BOOST_CHECK_EQUAL(v.size(), 0);
- BOOST_CHECK(v.setStr("zum"));
+ v.setStr("zum");
BOOST_CHECK(v.isStr());
BOOST_CHECK_EQUAL(v.getValStr(), "zum");
- BOOST_CHECK(v.setFloat(-1.01));
+ v.setFloat(-1.01);
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-1.01");
- BOOST_CHECK(v.setInt((int)1023));
+ v.setInt(int{1023});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "1023");
- BOOST_CHECK(v.setInt((int64_t)-1023LL));
+ v.setInt(int64_t{-1023LL});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-1023");
- BOOST_CHECK(v.setInt((uint64_t)1023ULL));
+ v.setInt(uint64_t{1023ULL});
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "1023");
- BOOST_CHECK(v.setNumStr("-688"));
+ v.setNumStr("-688");
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-688");
- BOOST_CHECK(v.setBool(false));
+ v.setBool(false);
BOOST_CHECK_EQUAL(v.isBool(), true);
BOOST_CHECK_EQUAL(v.isTrue(), false);
BOOST_CHECK_EQUAL(v.isFalse(), true);
BOOST_CHECK_EQUAL(v.getBool(), false);
- BOOST_CHECK(v.setBool(true));
+ v.setBool(true);
BOOST_CHECK_EQUAL(v.isBool(), true);
BOOST_CHECK_EQUAL(v.isTrue(), true);
BOOST_CHECK_EQUAL(v.isFalse(), false);
BOOST_CHECK_EQUAL(v.getBool(), true);
- BOOST_CHECK(!v.setNumStr("zombocom"));
+ BOOST_CHECK_THROW(v.setNumStr("zombocom"), std::runtime_error);
- BOOST_CHECK(v.setNull());
+ v.setNull();
BOOST_CHECK(v.isNull());
}
-BOOST_AUTO_TEST_CASE(univalue_array)
+void univalue_array()
{
UniValue arr(UniValue::VARR);
UniValue v((int64_t)1023LL);
- BOOST_CHECK(arr.push_back(v));
+ arr.push_back(v);
std::string vStr("zippy");
- BOOST_CHECK(arr.push_back(vStr));
+ arr.push_back(vStr);
const char *s = "pippy";
- BOOST_CHECK(arr.push_back(s));
+ arr.push_back(s);
std::vector<UniValue> vec;
v.setStr("boing");
@@ -213,13 +218,13 @@ BOOST_AUTO_TEST_CASE(univalue_array)
v.setStr("going");
vec.push_back(v);
- BOOST_CHECK(arr.push_backV(vec));
+ arr.push_backV(vec);
- BOOST_CHECK(arr.push_back((uint64_t) 400ULL));
- BOOST_CHECK(arr.push_back((int64_t) -400LL));
- BOOST_CHECK(arr.push_back((int) -401));
- BOOST_CHECK(arr.push_back(-40.1));
- BOOST_CHECK(arr.push_back(true));
+ arr.push_back(uint64_t{400ULL});
+ arr.push_back(int64_t{-400LL});
+ arr.push_back(int{-401});
+ arr.push_back(-40.1);
+ arr.push_back(true);
BOOST_CHECK_EQUAL(arr.empty(), false);
BOOST_CHECK_EQUAL(arr.size(), 10);
@@ -252,7 +257,7 @@ BOOST_AUTO_TEST_CASE(univalue_array)
BOOST_CHECK_EQUAL(arr.size(), 0);
}
-BOOST_AUTO_TEST_CASE(univalue_object)
+void univalue_object()
{
UniValue obj(UniValue::VOBJ);
std::string strKey, strVal;
@@ -260,39 +265,39 @@ BOOST_AUTO_TEST_CASE(univalue_object)
strKey = "age";
v.setInt(100);
- BOOST_CHECK(obj.pushKV(strKey, v));
+ obj.pushKV(strKey, v);
strKey = "first";
strVal = "John";
- BOOST_CHECK(obj.pushKV(strKey, strVal));
+ obj.pushKV(strKey, strVal);
strKey = "last";
- const char *cVal = "Smith";
- BOOST_CHECK(obj.pushKV(strKey, cVal));
+ const char* cVal = "Smith";
+ obj.pushKV(strKey, cVal);
strKey = "distance";
- BOOST_CHECK(obj.pushKV(strKey, (int64_t) 25));
+ obj.pushKV(strKey, int64_t{25});
strKey = "time";
- BOOST_CHECK(obj.pushKV(strKey, (uint64_t) 3600));
+ obj.pushKV(strKey, uint64_t{3600});
strKey = "calories";
- BOOST_CHECK(obj.pushKV(strKey, (int) 12));
+ obj.pushKV(strKey, int{12});
strKey = "temperature";
- BOOST_CHECK(obj.pushKV(strKey, (double) 90.012));
+ obj.pushKV(strKey, double{90.012});
strKey = "moon";
- BOOST_CHECK(obj.pushKV(strKey, true));
+ obj.pushKV(strKey, true);
strKey = "spoon";
- BOOST_CHECK(obj.pushKV(strKey, false));
+ obj.pushKV(strKey, false);
UniValue obj2(UniValue::VOBJ);
- BOOST_CHECK(obj2.pushKV("cat1", 9000));
- BOOST_CHECK(obj2.pushKV("cat2", 12345));
+ obj2.pushKV("cat1", 9000);
+ obj2.pushKV("cat2", 12345);
- BOOST_CHECK(obj.pushKVs(obj2));
+ obj.pushKVs(obj2);
BOOST_CHECK_EQUAL(obj.empty(), false);
BOOST_CHECK_EQUAL(obj.size(), 11);
@@ -347,7 +352,7 @@ BOOST_AUTO_TEST_CASE(univalue_object)
BOOST_CHECK_EQUAL(obj.size(), 0);
BOOST_CHECK_EQUAL(obj.getType(), UniValue::VNULL);
- BOOST_CHECK_EQUAL(obj.setObject(), true);
+ obj.setObject();
UniValue uv;
uv.setInt(42);
obj.__pushKV("age", uv);
@@ -371,7 +376,7 @@ BOOST_AUTO_TEST_CASE(univalue_object)
static const char *json1 =
"[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian http://test.com\"}}]";
-BOOST_AUTO_TEST_CASE(univalue_readwrite)
+void univalue_readwrite()
{
UniValue v;
BOOST_CHECK(v.read(json1));
@@ -414,11 +419,10 @@ BOOST_AUTO_TEST_CASE(univalue_readwrite)
BOOST_CHECK(!v.read("{} 42"));
}
-BOOST_AUTO_TEST_SUITE_END()
-
-int main (int argc, char *argv[])
+int main(int argc, char* argv[])
{
univalue_constructor();
+ univalue_push_throw();
univalue_typecheck();
univalue_set();
univalue_array();
@@ -426,4 +430,3 @@ int main (int argc, char *argv[])
univalue_readwrite();
return 0;
}
-
diff --git a/src/univalue/test/unitester.cpp b/src/univalue/test/unitester.cpp
index 94c149b39f..6344a5a0ab 100644
--- a/src/univalue/test/unitester.cpp
+++ b/src/univalue/test/unitester.cpp
@@ -149,6 +149,13 @@ void unescape_unicode_test()
assert(val[0].get_str() == "\xf0\x9d\x85\xa1");
}
+void no_nul_test()
+{
+ char buf[] = "___[1,2,3]___";
+ UniValue val;
+ assert(val.read(buf + 3, 7));
+}
+
int main (int argc, char *argv[])
{
for (const auto& f: filenames) {
@@ -156,6 +163,7 @@ int main (int argc, char *argv[])
}
unescape_unicode_test();
+ no_nul_test();
return 0;
}
diff --git a/src/util/asmap.cpp b/src/util/asmap.cpp
index ceb8379c1c..33258d9962 100644
--- a/src/util/asmap.cpp
+++ b/src/util/asmap.cpp
@@ -8,10 +8,13 @@
#include <crypto/common.h>
#include <fs.h>
#include <logging.h>
+#include <serialize.h>
#include <streams.h>
+#include <algorithm>
#include <cassert>
-#include <map>
+#include <cstdio>
+#include <utility>
#include <vector>
namespace {
@@ -195,7 +198,7 @@ std::vector<bool> DecodeAsmap(fs::path path)
{
std::vector<bool> bits;
FILE *filestr = fsbridge::fopen(path, "rb");
- CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
+ AutoFile file{filestr};
if (file.IsNull()) {
LogPrintf("Failed to open asmap file from disk\n");
return bits;
diff --git a/src/util/bip32.cpp b/src/util/bip32.cpp
index 4c7e948368..796af4a544 100644
--- a/src/util/bip32.cpp
+++ b/src/util/bip32.cpp
@@ -2,12 +2,13 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <sstream>
-#include <stdio.h>
#include <tinyformat.h>
#include <util/bip32.h>
#include <util/strencodings.h>
+#include <cstdint>
+#include <cstdio>
+#include <sstream>
bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath)
{
diff --git a/src/util/bip32.h b/src/util/bip32.h
index aa4eac3791..0872bc88de 100644
--- a/src/util/bip32.h
+++ b/src/util/bip32.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_UTIL_BIP32_H
#define BITCOIN_UTIL_BIP32_H
+#include <cstdint>
#include <string>
#include <vector>
diff --git a/src/util/bitdeque.h b/src/util/bitdeque.h
new file mode 100644
index 0000000000..1e34b72475
--- /dev/null
+++ b/src/util/bitdeque.h
@@ -0,0 +1,469 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_BITDEQUE_H
+#define BITCOIN_UTIL_BITDEQUE_H
+
+#include <bitset>
+#include <cstddef>
+#include <deque>
+#include <limits>
+#include <stdexcept>
+#include <tuple>
+
+/** Class that mimics std::deque<bool>, but with std::vector<bool>'s bit packing.
+ *
+ * BlobSize selects the (minimum) number of bits that are allocated at once.
+ * Larger values reduce the asymptotic memory usage overhead, at the cost of
+ * needing larger up-front allocations. The default is 4096 bytes.
+ */
+template<int BlobSize = 4096 * 8>
+class bitdeque
+{
+ // Internal definitions
+ using word_type = std::bitset<BlobSize>;
+ using deque_type = std::deque<word_type>;
+ static_assert(BlobSize > 0);
+ static constexpr int BITS_PER_WORD = BlobSize;
+
+ // Forward and friend declarations of iterator types.
+ template<bool Const> class Iterator;
+ template<bool Const> friend class Iterator;
+
+ /** Iterator to a bitdeque element, const or not. */
+ template<bool Const>
+ class Iterator
+ {
+ using deque_iterator = std::conditional_t<Const, typename deque_type::const_iterator, typename deque_type::iterator>;
+
+ deque_iterator m_it;
+ int m_bitpos{0};
+ Iterator(const deque_iterator& it, int bitpos) : m_it(it), m_bitpos(bitpos) {}
+ friend class bitdeque;
+
+ public:
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = bool;
+ using pointer = void;
+ using const_pointer = void;
+ using reference = std::conditional_t<Const, bool, typename word_type::reference>;
+ using const_reference = bool;
+ using difference_type = std::ptrdiff_t;
+
+ /** Default constructor. */
+ Iterator() = default;
+
+ /** Default copy constructor. */
+ Iterator(const Iterator&) = default;
+
+ /** Conversion from non-const to const iterator. */
+ template<bool ConstArg = Const, typename = std::enable_if_t<Const && ConstArg>>
+ Iterator(const Iterator<false>& x) : m_it(x.m_it), m_bitpos(x.m_bitpos) {}
+
+ Iterator& operator+=(difference_type dist)
+ {
+ if (dist > 0) {
+ if (dist + m_bitpos >= BITS_PER_WORD) {
+ ++m_it;
+ dist -= BITS_PER_WORD - m_bitpos;
+ m_bitpos = 0;
+ }
+ auto jump = dist / BITS_PER_WORD;
+ m_it += jump;
+ m_bitpos += dist - jump * BITS_PER_WORD;
+ } else if (dist < 0) {
+ dist = -dist;
+ if (dist > m_bitpos) {
+ --m_it;
+ dist -= m_bitpos + 1;
+ m_bitpos = BITS_PER_WORD - 1;
+ }
+ auto jump = dist / BITS_PER_WORD;
+ m_it -= jump;
+ m_bitpos -= dist - jump * BITS_PER_WORD;
+ }
+ return *this;
+ }
+
+ friend difference_type operator-(const Iterator& x, const Iterator& y)
+ {
+ return BITS_PER_WORD * (x.m_it - y.m_it) + x.m_bitpos - y.m_bitpos;
+ }
+
+ Iterator& operator=(const Iterator&) = default;
+ Iterator& operator-=(difference_type dist) { return operator+=(-dist); }
+ Iterator& operator++() { ++m_bitpos; if (m_bitpos == BITS_PER_WORD) { m_bitpos = 0; ++m_it; }; return *this; }
+ Iterator operator++(int) { auto ret{*this}; operator++(); return ret; }
+ Iterator& operator--() { if (m_bitpos == 0) { m_bitpos = BITS_PER_WORD; --m_it; }; --m_bitpos; return *this; }
+ Iterator operator--(int) { auto ret{*this}; operator--(); return ret; }
+ friend Iterator operator+(Iterator x, difference_type dist) { x += dist; return x; }
+ friend Iterator operator+(difference_type dist, Iterator x) { x += dist; return x; }
+ friend Iterator operator-(Iterator x, difference_type dist) { x -= dist; return x; }
+ friend bool operator<(const Iterator& x, const Iterator& y) { return std::tie(x.m_it, x.m_bitpos) < std::tie(y.m_it, y.m_bitpos); }
+ friend bool operator>(const Iterator& x, const Iterator& y) { return std::tie(x.m_it, x.m_bitpos) > std::tie(y.m_it, y.m_bitpos); }
+ friend bool operator<=(const Iterator& x, const Iterator& y) { return std::tie(x.m_it, x.m_bitpos) <= std::tie(y.m_it, y.m_bitpos); }
+ friend bool operator>=(const Iterator& x, const Iterator& y) { return std::tie(x.m_it, x.m_bitpos) >= std::tie(y.m_it, y.m_bitpos); }
+ friend bool operator==(const Iterator& x, const Iterator& y) { return x.m_it == y.m_it && x.m_bitpos == y.m_bitpos; }
+ friend bool operator!=(const Iterator& x, const Iterator& y) { return x.m_it != y.m_it || x.m_bitpos != y.m_bitpos; }
+ reference operator*() const { return (*m_it)[m_bitpos]; }
+ reference operator[](difference_type pos) const { return *(*this + pos); }
+ };
+
+public:
+ using value_type = bool;
+ using size_type = std::size_t;
+ using difference_type = typename deque_type::difference_type;
+ using reference = typename word_type::reference;
+ using const_reference = bool;
+ using iterator = Iterator<false>;
+ using const_iterator = Iterator<true>;
+ using pointer = void;
+ using const_pointer = void;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+private:
+ /** Deque of bitsets storing the actual bit data. */
+ deque_type m_deque;
+
+ /** Number of unused bits at the front of m_deque.front(). */
+ int m_pad_begin;
+
+ /** Number of unused bits at the back of m_deque.back(). */
+ int m_pad_end;
+
+ /** Shrink the container by n bits, removing from the end. */
+ void erase_back(size_type n)
+ {
+ if (n >= static_cast<size_type>(BITS_PER_WORD - m_pad_end)) {
+ n -= BITS_PER_WORD - m_pad_end;
+ m_pad_end = 0;
+ m_deque.erase(m_deque.end() - 1 - (n / BITS_PER_WORD), m_deque.end());
+ n %= BITS_PER_WORD;
+ }
+ if (n) {
+ auto& last = m_deque.back();
+ while (n) {
+ last.reset(BITS_PER_WORD - 1 - m_pad_end);
+ ++m_pad_end;
+ --n;
+ }
+ }
+ }
+
+ /** Extend the container by n bits, adding at the end. */
+ void extend_back(size_type n)
+ {
+ if (n > static_cast<size_type>(m_pad_end)) {
+ n -= m_pad_end + 1;
+ m_pad_end = BITS_PER_WORD - 1;
+ m_deque.insert(m_deque.end(), 1 + (n / BITS_PER_WORD), {});
+ n %= BITS_PER_WORD;
+ }
+ m_pad_end -= n;
+ }
+
+ /** Shrink the container by n bits, removing from the beginning. */
+ void erase_front(size_type n)
+ {
+ if (n >= static_cast<size_type>(BITS_PER_WORD - m_pad_begin)) {
+ n -= BITS_PER_WORD - m_pad_begin;
+ m_pad_begin = 0;
+ m_deque.erase(m_deque.begin(), m_deque.begin() + 1 + (n / BITS_PER_WORD));
+ n %= BITS_PER_WORD;
+ }
+ if (n) {
+ auto& first = m_deque.front();
+ while (n) {
+ first.reset(m_pad_begin);
+ ++m_pad_begin;
+ --n;
+ }
+ }
+ }
+
+ /** Extend the container by n bits, adding at the beginning. */
+ void extend_front(size_type n)
+ {
+ if (n > static_cast<size_type>(m_pad_begin)) {
+ n -= m_pad_begin + 1;
+ m_pad_begin = BITS_PER_WORD - 1;
+ m_deque.insert(m_deque.begin(), 1 + (n / BITS_PER_WORD), {});
+ n %= BITS_PER_WORD;
+ }
+ m_pad_begin -= n;
+ }
+
+ /** Insert a sequence of falses anywhere in the container. */
+ void insert_zeroes(size_type before, size_type count)
+ {
+ size_type after = size() - before;
+ if (before < after) {
+ extend_front(count);
+ std::move(begin() + count, begin() + count + before, begin());
+ } else {
+ extend_back(count);
+ std::move_backward(begin() + before, begin() + before + after, end());
+ }
+ }
+
+public:
+ /** Construct an empty container. */
+ explicit bitdeque() : m_pad_begin{0}, m_pad_end{0} {}
+
+ /** Set the container equal to count times the value of val. */
+ void assign(size_type count, bool val)
+ {
+ m_deque.clear();
+ m_deque.resize((count + BITS_PER_WORD - 1) / BITS_PER_WORD);
+ m_pad_begin = 0;
+ m_pad_end = 0;
+ if (val) {
+ for (auto& elem : m_deque) elem.flip();
+ }
+ if (count % BITS_PER_WORD) {
+ erase_back(BITS_PER_WORD - (count % BITS_PER_WORD));
+ }
+ }
+
+ /** Construct a container containing count times the value of val. */
+ bitdeque(size_type count, bool val) { assign(count, val); }
+
+ /** Construct a container containing count false values. */
+ explicit bitdeque(size_t count) { assign(count, false); }
+
+ /** Copy constructor. */
+ bitdeque(const bitdeque&) = default;
+
+ /** Move constructor. */
+ bitdeque(bitdeque&&) noexcept = default;
+
+ /** Copy assignment operator. */
+ bitdeque& operator=(const bitdeque& other) = default;
+
+ /** Move assignment operator. */
+ bitdeque& operator=(bitdeque&& other) noexcept = default;
+
+ // Iterator functions.
+ iterator begin() noexcept { return {m_deque.begin(), m_pad_begin}; }
+ iterator end() noexcept { return iterator{m_deque.end(), 0} - m_pad_end; }
+ const_iterator begin() const noexcept { return const_iterator{m_deque.cbegin(), m_pad_begin}; }
+ const_iterator cbegin() const noexcept { return const_iterator{m_deque.cbegin(), m_pad_begin}; }
+ const_iterator end() const noexcept { return const_iterator{m_deque.cend(), 0} - m_pad_end; }
+ const_iterator cend() const noexcept { return const_iterator{m_deque.cend(), 0} - m_pad_end; }
+ reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; }
+ reverse_iterator rend() noexcept { return reverse_iterator{begin()}; }
+ const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{cend()}; }
+ const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{cend()}; }
+ const_reverse_iterator rend() const noexcept { return const_reverse_iterator{cbegin()}; }
+ const_reverse_iterator crend() const noexcept { return const_reverse_iterator{cbegin()}; }
+
+ /** Count the number of bits in the container. */
+ size_type size() const noexcept { return m_deque.size() * BITS_PER_WORD - m_pad_begin - m_pad_end; }
+
+ /** Determine whether the container is empty. */
+ bool empty() const noexcept
+ {
+ return m_deque.size() == 0 || (m_deque.size() == 1 && (m_pad_begin + m_pad_end == BITS_PER_WORD));
+ }
+
+ /** Return the maximum size of the container. */
+ size_type max_size() const noexcept
+ {
+ if (m_deque.max_size() < std::numeric_limits<difference_type>::max() / BITS_PER_WORD) {
+ return m_deque.max_size() * BITS_PER_WORD;
+ } else {
+ return std::numeric_limits<difference_type>::max();
+ }
+ }
+
+ /** Set the container equal to the bits in [first,last). */
+ template<typename It>
+ void assign(It first, It last)
+ {
+ size_type count = std::distance(first, last);
+ assign(count, false);
+ auto it = begin();
+ while (first != last) {
+ *(it++) = *(first++);
+ }
+ }
+
+ /** Set the container equal to the bits in ilist. */
+ void assign(std::initializer_list<bool> ilist)
+ {
+ assign(ilist.size(), false);
+ auto it = begin();
+ auto init = ilist.begin();
+ while (init != ilist.end()) {
+ *(it++) = *(init++);
+ }
+ }
+
+ /** Set the container equal to the bits in ilist. */
+ bitdeque& operator=(std::initializer_list<bool> ilist)
+ {
+ assign(ilist);
+ return *this;
+ }
+
+ /** Construct a container containing the bits in [first,last). */
+ template<typename It>
+ bitdeque(It first, It last) { assign(first, last); }
+
+ /** Construct a container containing the bits in ilist. */
+ bitdeque(std::initializer_list<bool> ilist) { assign(ilist); }
+
+ // Access an element of the container, with bounds checking.
+ reference at(size_type position)
+ {
+ if (position >= size()) throw std::out_of_range("bitdeque::at() out of range");
+ return begin()[position];
+ }
+ const_reference at(size_type position) const
+ {
+ if (position >= size()) throw std::out_of_range("bitdeque::at() out of range");
+ return cbegin()[position];
+ }
+
+ // Access elements of the container without bounds checking.
+ reference operator[](size_type position) { return begin()[position]; }
+ const_reference operator[](size_type position) const { return cbegin()[position]; }
+ reference front() { return *begin(); }
+ const_reference front() const { return *cbegin(); }
+ reference back() { return end()[-1]; }
+ const_reference back() const { return cend()[-1]; }
+
+ /** Release unused memory. */
+ void shrink_to_fit()
+ {
+ m_deque.shrink_to_fit();
+ }
+
+ /** Empty the container. */
+ void clear() noexcept
+ {
+ m_deque.clear();
+ m_pad_begin = m_pad_end = 0;
+ }
+
+ // Append an element to the container.
+ void push_back(bool val)
+ {
+ extend_back(1);
+ back() = val;
+ }
+ reference emplace_back(bool val)
+ {
+ extend_back(1);
+ auto ref = back();
+ ref = val;
+ return ref;
+ }
+
+ // Prepend an element to the container.
+ void push_front(bool val)
+ {
+ extend_front(1);
+ front() = val;
+ }
+ reference emplace_front(bool val)
+ {
+ extend_front(1);
+ auto ref = front();
+ ref = val;
+ return ref;
+ }
+
+ // Remove the last element from the container.
+ void pop_back()
+ {
+ erase_back(1);
+ }
+
+ // Remove the first element from the container.
+ void pop_front()
+ {
+ erase_front(1);
+ }
+
+ /** Resize the container. */
+ void resize(size_type n)
+ {
+ if (n < size()) {
+ erase_back(size() - n);
+ } else {
+ extend_back(n - size());
+ }
+ }
+
+ // Swap two containers.
+ void swap(bitdeque& other) noexcept
+ {
+ std::swap(m_deque, other.m_deque);
+ std::swap(m_pad_begin, other.m_pad_begin);
+ std::swap(m_pad_end, other.m_pad_end);
+ }
+ friend void swap(bitdeque& b1, bitdeque& b2) noexcept { b1.swap(b2); }
+
+ // Erase elements from the container.
+ iterator erase(const_iterator first, const_iterator last)
+ {
+ size_type before = std::distance(cbegin(), first);
+ size_type dist = std::distance(first, last);
+ size_type after = std::distance(last, cend());
+ if (before < after) {
+ std::move_backward(begin(), begin() + before, end() - after);
+ erase_front(dist);
+ return begin() + before;
+ } else {
+ std::move(end() - after, end(), begin() + before);
+ erase_back(dist);
+ return end() - after;
+ }
+ }
+
+ iterator erase(iterator first, iterator last) { return erase(const_iterator{first}, const_iterator{last}); }
+ iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
+ iterator erase(iterator pos) { return erase(const_iterator{pos}, const_iterator{pos} + 1); }
+
+ // Insert elements into the container.
+ iterator insert(const_iterator pos, bool val)
+ {
+ size_type before = pos - cbegin();
+ insert_zeroes(before, 1);
+ auto it = begin() + before;
+ *it = val;
+ return it;
+ }
+
+ iterator emplace(const_iterator pos, bool val) { return insert(pos, val); }
+
+ iterator insert(const_iterator pos, size_type count, bool val)
+ {
+ size_type before = pos - cbegin();
+ insert_zeroes(before, count);
+ auto it_begin = begin() + before;
+ auto it = it_begin;
+ auto it_end = it + count;
+ while (it != it_end) *(it++) = val;
+ return it_begin;
+ }
+
+ template<typename It>
+ iterator insert(const_iterator pos, It first, It last)
+ {
+ size_type before = pos - cbegin();
+ size_type count = std::distance(first, last);
+ insert_zeroes(before, count);
+ auto it_begin = begin() + before;
+ auto it = it_begin;
+ while (first != last) {
+ *(it++) = *(first++);
+ }
+ return it_begin;
+ }
+};
+
+#endif // BITCOIN_UTIL_BITDEQUE_H
diff --git a/src/util/bytevectorhash.cpp b/src/util/bytevectorhash.cpp
index 9054db4759..6d777613e6 100644
--- a/src/util/bytevectorhash.cpp
+++ b/src/util/bytevectorhash.cpp
@@ -6,6 +6,8 @@
#include <random.h>
#include <util/bytevectorhash.h>
+#include <vector>
+
ByteVectorHash::ByteVectorHash() :
m_k0(GetRand<uint64_t>()),
m_k1(GetRand<uint64_t>())
diff --git a/src/util/bytevectorhash.h b/src/util/bytevectorhash.h
index b88c17460b..c2322b8daf 100644
--- a/src/util/bytevectorhash.h
+++ b/src/util/bytevectorhash.h
@@ -5,7 +5,8 @@
#ifndef BITCOIN_UTIL_BYTEVECTORHASH_H
#define BITCOIN_UTIL_BYTEVECTORHASH_H
-#include <stdint.h>
+#include <cstdint>
+#include <cstddef>
#include <vector>
/**
diff --git a/src/util/designator.h b/src/util/designator.h
deleted file mode 100644
index 3670b11e00..0000000000
--- a/src/util/designator.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2022 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_UTIL_DESIGNATOR_H
-#define BITCOIN_UTIL_DESIGNATOR_H
-
-/**
- * Designated initializers can be used to avoid ordering mishaps in aggregate
- * initialization. However, they do not prevent uninitialized members. The
- * checks can be disabled by defining DISABLE_DESIGNATED_INITIALIZER_ERRORS.
- * This should only be needed on MSVC 2019. MSVC 2022 supports them with the
- * option "/std:c++20"
- */
-#ifndef DISABLE_DESIGNATED_INITIALIZER_ERRORS
-#define Desig(field_name) .field_name =
-#else
-#define Desig(field_name)
-#endif
-
-#endif // BITCOIN_UTIL_DESIGNATOR_H
diff --git a/src/util/error.cpp b/src/util/error.cpp
index af8cbd0353..33a35a6d59 100644
--- a/src/util/error.cpp
+++ b/src/util/error.cpp
@@ -5,9 +5,11 @@
#include <util/error.h>
#include <tinyformat.h>
-#include <util/system.h>
#include <util/translation.h>
+#include <cassert>
+#include <string>
+
bilingual_str TransactionErrorString(const TransactionError err)
{
switch (err) {
@@ -35,6 +37,8 @@ bilingual_str TransactionErrorString(const TransactionError err)
return Untranslated("External signer not found");
case TransactionError::EXTERNAL_SIGNER_FAILED:
return Untranslated("External signer failed to sign");
+ case TransactionError::INVALID_PACKAGE:
+ return Untranslated("Transaction rejected due to invalid package");
// no default case, so the compiler can warn about missing cases
}
assert(false);
diff --git a/src/util/error.h b/src/util/error.h
index 4cc35eb1fd..0429de651a 100644
--- a/src/util/error.h
+++ b/src/util/error.h
@@ -32,6 +32,7 @@ enum class TransactionError {
MAX_FEE_EXCEEDED,
EXTERNAL_SIGNER_NOT_FOUND,
EXTERNAL_SIGNER_FAILED,
+ INVALID_PACKAGE,
};
bilingual_str TransactionErrorString(const TransactionError error);
diff --git a/src/util/hasher.cpp b/src/util/hasher.cpp
index c21941eb88..a80f20c894 100644
--- a/src/util/hasher.cpp
+++ b/src/util/hasher.cpp
@@ -2,11 +2,11 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <crypto/siphash.h>
#include <random.h>
+#include <span.h>
#include <util/hasher.h>
-#include <limits>
-
SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand<uint64_t>()), k1(GetRand<uint64_t>()) {}
SaltedOutpointHasher::SaltedOutpointHasher() : k0(GetRand<uint64_t>()), k1(GetRand<uint64_t>()) {}
diff --git a/src/util/hasher.h b/src/util/hasher.h
index 3d24a4d23c..426b8990e6 100644
--- a/src/util/hasher.h
+++ b/src/util/hasher.h
@@ -5,10 +5,16 @@
#ifndef BITCOIN_UTIL_HASHER_H
#define BITCOIN_UTIL_HASHER_H
+#include <crypto/common.h>
#include <crypto/siphash.h>
#include <primitives/transaction.h>
#include <uint256.h>
+#include <cstdint>
+#include <cstring>
+
+template <typename C> class Span;
+
class SaltedTxidHasher
{
private:
diff --git a/src/util/message.cpp b/src/util/message.cpp
index f58876f915..7d6f3403f4 100644
--- a/src/util/message.cpp
+++ b/src/util/message.cpp
@@ -3,16 +3,19 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <hash.h> // For CHashWriter
-#include <key.h> // For CKey
-#include <key_io.h> // For DecodeDestination()
-#include <pubkey.h> // For CPubKey
-#include <script/standard.h> // For CTxDestination, IsValidDestination(), PKHash
-#include <serialize.h> // For SER_GETHASH
+#include <hash.h>
+#include <key.h>
+#include <key_io.h>
+#include <pubkey.h>
+#include <script/standard.h>
+#include <uint256.h>
#include <util/message.h>
-#include <util/strencodings.h> // For DecodeBase64()
+#include <util/strencodings.h>
+#include <cassert>
+#include <optional>
#include <string>
+#include <variant>
#include <vector>
/**
@@ -70,7 +73,7 @@ bool MessageSign(
uint256 MessageHash(const std::string& message)
{
- CHashWriter hasher(SER_GETHASH, 0);
+ HashWriter hasher{};
hasher << MESSAGE_MAGIC << message;
return hasher.GetHash();
diff --git a/src/util/message.h b/src/util/message.h
index b31c5f5761..1b7febe60a 100644
--- a/src/util/message.h
+++ b/src/util/message.h
@@ -6,11 +6,12 @@
#ifndef BITCOIN_UTIL_MESSAGE_H
#define BITCOIN_UTIL_MESSAGE_H
-#include <key.h> // For CKey
#include <uint256.h>
#include <string>
+class CKey;
+
extern const std::string MESSAGE_MAGIC;
/** The result of a signed message verification.
diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp
index 8c4bc6e6f4..d9e6cef600 100644
--- a/src/util/moneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -10,6 +10,7 @@
#include <util/strencodings.h>
#include <util/string.h>
+#include <cstdint>
#include <optional>
std::string FormatMoney(const CAmount n)
diff --git a/src/util/readwritefile.cpp b/src/util/readwritefile.cpp
index 628e6a3980..3ec08119e7 100644
--- a/src/util/readwritefile.cpp
+++ b/src/util/readwritefile.cpp
@@ -5,8 +5,9 @@
#include <fs.h>
+#include <algorithm>
+#include <cstdio>
#include <limits>
-#include <stdio.h>
#include <string>
#include <utility>
diff --git a/src/util/result.h b/src/util/result.h
new file mode 100644
index 0000000000..972b1aada0
--- /dev/null
+++ b/src/util/result.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or https://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_UTIL_RESULT_H
+#define BITCOIN_UTIL_RESULT_H
+
+#include <attributes.h>
+#include <util/translation.h>
+
+#include <variant>
+
+namespace util {
+
+struct Error {
+ bilingual_str message;
+};
+
+//! The util::Result class provides a standard way for functions to return
+//! either error messages or result values.
+//!
+//! It is intended for high-level functions that need to report error strings to
+//! end users. Lower-level functions that don't need this error-reporting and
+//! only need error-handling should avoid util::Result and instead use standard
+//! classes like std::optional, std::variant, and std::tuple, or custom structs
+//! and enum types to return function results.
+//!
+//! Usage examples can be found in \example ../test/result_tests.cpp, but in
+//! general code returning `util::Result<T>` values is very similar to code
+//! returning `std::optional<T>` values. Existing functions returning
+//! `std::optional<T>` can be updated to return `util::Result<T>` and return
+//! error strings usually just replacing `return std::nullopt;` with `return
+//! util::Error{error_string};`.
+template <class T>
+class Result
+{
+private:
+ std::variant<bilingual_str, T> m_variant;
+
+ template <typename FT>
+ friend bilingual_str ErrorString(const Result<FT>& result);
+
+public:
+ Result(T obj) : m_variant{std::in_place_index_t<1>{}, std::move(obj)} {}
+ Result(Error error) : m_variant{std::in_place_index_t<0>{}, std::move(error.message)} {}
+
+ //! std::optional methods, so functions returning optional<T> can change to
+ //! return Result<T> with minimal changes to existing code, and vice versa.
+ bool has_value() const noexcept { return m_variant.index() == 1; }
+ const T& value() const LIFETIMEBOUND
+ {
+ assert(has_value());
+ return std::get<1>(m_variant);
+ }
+ T& value() LIFETIMEBOUND
+ {
+ assert(has_value());
+ return std::get<1>(m_variant);
+ }
+ template <class U>
+ T value_or(U&& default_value) const&
+ {
+ return has_value() ? value() : std::forward<U>(default_value);
+ }
+ template <class U>
+ T value_or(U&& default_value) &&
+ {
+ return has_value() ? std::move(value()) : std::forward<U>(default_value);
+ }
+ explicit operator bool() const noexcept { return has_value(); }
+ const T* operator->() const LIFETIMEBOUND { return &value(); }
+ const T& operator*() const LIFETIMEBOUND { return value(); }
+ T* operator->() LIFETIMEBOUND { return &value(); }
+ T& operator*() LIFETIMEBOUND { return value(); }
+};
+
+template <typename T>
+bilingual_str ErrorString(const Result<T>& result)
+{
+ return result ? bilingual_str{} : std::get<0>(result.m_variant);
+}
+} // namespace util
+
+#endif // BITCOIN_UTIL_RESULT_H
diff --git a/src/util/serfloat.h b/src/util/serfloat.h
index 4d912b0176..343ccb9d3a 100644
--- a/src/util/serfloat.h
+++ b/src/util/serfloat.h
@@ -5,7 +5,7 @@
#ifndef BITCOIN_UTIL_SERFLOAT_H
#define BITCOIN_UTIL_SERFLOAT_H
-#include <stdint.h>
+#include <cstdint>
/* Encode a double using the IEEE 754 binary64 format. All NaNs are encoded as x86/ARM's
* positive quiet NaN with payload 0. */
diff --git a/src/util/sock.cpp b/src/util/sock.cpp
index 7d5069423a..125dbc7f18 100644
--- a/src/util/sock.cpp
+++ b/src/util/sock.cpp
@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <compat.h>
+#include <compat/compat.h>
#include <logging.h>
#include <threadinterrupt.h>
#include <tinyformat.h>
@@ -39,11 +39,11 @@ Sock::Sock(Sock&& other)
other.m_socket = INVALID_SOCKET;
}
-Sock::~Sock() { Reset(); }
+Sock::~Sock() { Close(); }
Sock& Sock::operator=(Sock&& other)
{
- Reset();
+ Close();
m_socket = other.m_socket;
other.m_socket = INVALID_SOCKET;
return *this;
@@ -51,15 +51,6 @@ Sock& Sock::operator=(Sock&& other)
SOCKET Sock::Get() const { return m_socket; }
-SOCKET Sock::Release()
-{
- const SOCKET s = m_socket;
- m_socket = INVALID_SOCKET;
- return s;
-}
-
-void Sock::Reset() { CloseSocket(m_socket); }
-
ssize_t Sock::Send(const void* data, size_t len, int flags) const
{
return send(m_socket, static_cast<const char*>(data), len, flags);
@@ -75,6 +66,16 @@ int Sock::Connect(const sockaddr* addr, socklen_t addr_len) const
return connect(m_socket, addr, addr_len);
}
+int Sock::Bind(const sockaddr* addr, socklen_t addr_len) const
+{
+ return bind(m_socket, addr, addr_len);
+}
+
+int Sock::Listen(int backlog) const
+{
+ return listen(m_socket, backlog);
+}
+
std::unique_ptr<Sock> Sock::Accept(sockaddr* addr, socklen_t* addr_len) const
{
#ifdef WIN32
@@ -111,6 +112,11 @@ int Sock::SetSockOpt(int level, int opt_name, const void* opt_val, socklen_t opt
return setsockopt(m_socket, level, opt_name, static_cast<const char*>(opt_val), opt_len);
}
+int Sock::GetSockName(sockaddr* name, socklen_t* name_len) const
+{
+ return getsockname(m_socket, name, name_len);
+}
+
bool Sock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const
{
// We need a `shared_ptr` owning `this` for `WaitMany()`, but don't want
@@ -366,6 +372,22 @@ bool Sock::IsConnected(std::string& errmsg) const
}
}
+void Sock::Close()
+{
+ if (m_socket == INVALID_SOCKET) {
+ return;
+ }
+#ifdef WIN32
+ int ret = closesocket(m_socket);
+#else
+ int ret = close(m_socket);
+#endif
+ if (ret) {
+ LogPrintf("Error closing socket %d: %s\n", m_socket, NetworkErrorString(WSAGetLastError()));
+ }
+ m_socket = INVALID_SOCKET;
+}
+
#ifdef WIN32
std::string NetworkErrorString(int err)
{
@@ -389,19 +411,3 @@ std::string NetworkErrorString(int err)
return SysErrorString(err);
}
#endif
-
-bool CloseSocket(SOCKET& hSocket)
-{
- if (hSocket == INVALID_SOCKET)
- return false;
-#ifdef WIN32
- int ret = closesocket(hSocket);
-#else
- int ret = close(hSocket);
-#endif
- if (ret) {
- LogPrintf("Socket close failed: %d. Error: %s\n", hSocket, NetworkErrorString(WSAGetLastError()));
- }
- hSocket = INVALID_SOCKET;
- return ret != SOCKET_ERROR;
-}
diff --git a/src/util/sock.h b/src/util/sock.h
index 3245820995..38a7dc80d6 100644
--- a/src/util/sock.h
+++ b/src/util/sock.h
@@ -5,7 +5,7 @@
#ifndef BITCOIN_UTIL_SOCK_H
#define BITCOIN_UTIL_SOCK_H
-#include <compat.h>
+#include <compat/compat.h>
#include <threadinterrupt.h>
#include <util/time.h>
@@ -69,18 +69,6 @@ public:
[[nodiscard]] virtual SOCKET Get() const;
/**
- * Get the value of the contained socket and drop ownership. It will not be closed by the
- * destructor after this call.
- * @return socket or INVALID_SOCKET if empty
- */
- virtual SOCKET Release();
-
- /**
- * Close if non-empty.
- */
- virtual void Reset();
-
- /**
* send(2) wrapper. Equivalent to `send(this->Get(), data, len, flags);`. Code that uses this
* wrapper can be unit tested if this method is overridden by a mock Sock implementation.
*/
@@ -99,6 +87,18 @@ public:
[[nodiscard]] virtual int Connect(const sockaddr* addr, socklen_t addr_len) const;
/**
+ * bind(2) wrapper. Equivalent to `bind(this->Get(), addr, addr_len)`. Code that uses this
+ * wrapper can be unit tested if this method is overridden by a mock Sock implementation.
+ */
+ [[nodiscard]] virtual int Bind(const sockaddr* addr, socklen_t addr_len) const;
+
+ /**
+ * listen(2) wrapper. Equivalent to `listen(this->Get(), backlog)`. Code that uses this
+ * wrapper can be unit tested if this method is overridden by a mock Sock implementation.
+ */
+ [[nodiscard]] virtual int Listen(int backlog) const;
+
+ /**
* accept(2) wrapper. Equivalent to `std::make_unique<Sock>(accept(this->Get(), addr, addr_len))`.
* Code that uses this wrapper can be unit tested if this method is overridden by a mock Sock
* implementation.
@@ -126,6 +126,13 @@ public:
const void* opt_val,
socklen_t opt_len) const;
+ /**
+ * getsockname(2) wrapper. Equivalent to
+ * `getsockname(this->Get(), name, name_len)`. Code that uses this
+ * wrapper can be unit tested if this method is overridden by a mock Sock implementation.
+ */
+ [[nodiscard]] virtual int GetSockName(sockaddr* name, socklen_t* name_len) const;
+
using Event = uint8_t;
/**
@@ -252,12 +259,15 @@ protected:
* Contained socket. `INVALID_SOCKET` designates the object is empty.
*/
SOCKET m_socket;
+
+private:
+ /**
+ * Close `m_socket` if it is not `INVALID_SOCKET`.
+ */
+ void Close();
};
/** Return readable error string for a network error code */
std::string NetworkErrorString(int err);
-/** Close socket and set hSocket to INVALID_SOCKET */
-bool CloseSocket(SOCKET& hSocket);
-
#endif // BITCOIN_UTIL_SOCK_H
diff --git a/src/util/spanparsing.cpp b/src/util/spanparsing.cpp
index 8614bd1176..565c867e18 100644
--- a/src/util/spanparsing.cpp
+++ b/src/util/spanparsing.cpp
@@ -6,8 +6,9 @@
#include <span.h>
+#include <algorithm>
+#include <cstddef>
#include <string>
-#include <vector>
namespace spanparsing {
diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp
index 675fe7d2d7..b5ac151374 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -3,17 +3,17 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <span.h>
#include <util/strencodings.h>
-#include <util/string.h>
-#include <tinyformat.h>
-
-#include <algorithm>
#include <array>
-#include <cstdlib>
+#include <cassert>
#include <cstring>
#include <limits>
#include <optional>
+#include <ostream>
+#include <string>
+#include <vector>
static const std::string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 9a96bbe67b..14867b21b2 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -13,11 +13,14 @@
#include <util/string.h>
#include <charconv>
+#include <cstddef>
#include <cstdint>
-#include <iterator>
#include <limits>
#include <optional>
#include <string>
+#include <string_view>
+#include <system_error>
+#include <type_traits>
#include <vector>
/** Used by SanitizeString() */
diff --git a/src/util/string.cpp b/src/util/string.cpp
index d05222e8b8..e994c85f1c 100644
--- a/src/util/string.cpp
+++ b/src/util/string.cpp
@@ -4,9 +4,11 @@
#include <util/string.h>
-#include <boost/algorithm/string/replace.hpp>
+#include <regex>
+#include <string>
-void ReplaceAll(std::string& in_out, std::string_view search, std::string_view substitute)
+void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute)
{
- boost::replace_all(in_out, search, substitute);
+ if (search.empty()) return;
+ in_out = std::regex_replace(in_out, std::regex(search), substitute);
}
diff --git a/src/util/string.h b/src/util/string.h
index df20e34ae9..9b4c9a7e28 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -7,7 +7,6 @@
#include <util/spanparsing.h>
-#include <algorithm>
#include <array>
#include <cstdint>
#include <cstring>
@@ -17,7 +16,7 @@
#include <string_view>
#include <vector>
-void ReplaceAll(std::string& in_out, std::string_view search, std::string_view substitute);
+void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute);
[[nodiscard]] inline std::vector<std::string> SplitString(std::string_view str, char sep)
{
@@ -58,34 +57,30 @@ void ReplaceAll(std::string& in_out, std::string_view search, std::string_view s
}
/**
- * Join a list of items
+ * Join all container items. Typically used to concatenate strings but accepts
+ * containers with elements of any type.
*
- * @param list The list to join
- * @param separator The separator
- * @param unary_op Apply this operator to each item in the list
+ * @param container The items to join
+ * @param separator The separator
+ * @param unary_op Apply this operator to each item
*/
-template <typename T, typename BaseType, typename UnaryOp>
-auto Join(const std::vector<T>& list, const BaseType& separator, UnaryOp unary_op)
- -> decltype(unary_op(list.at(0)))
+template <typename C, typename S, typename UnaryOp>
+auto Join(const C& container, const S& separator, UnaryOp unary_op)
{
- decltype(unary_op(list.at(0))) ret;
- for (size_t i = 0; i < list.size(); ++i) {
- if (i > 0) ret += separator;
- ret += unary_op(list.at(i));
+ decltype(unary_op(*container.begin())) ret;
+ bool first{true};
+ for (const auto& item : container) {
+ if (!first) ret += separator;
+ ret += unary_op(item);
+ first = false;
}
return ret;
}
-template <typename T, typename T2>
-T Join(const std::vector<T>& list, const T2& separator)
+template <typename C, typename S>
+auto Join(const C& container, const S& separator)
{
- return Join(list, separator, [](const T& i) { return i; });
-}
-
-// Explicit overload needed for c_str arguments, which would otherwise cause a substitution failure in the template above.
-inline std::string Join(const std::vector<std::string>& list, std::string_view separator)
-{
- return Join<std::string>(list, separator);
+ return Join(container, separator, [](const auto& i) { return i; });
}
/**
diff --git a/src/util/syserror.cpp b/src/util/syserror.cpp
index 391ddd3560..5270f55366 100644
--- a/src/util/syserror.cpp
+++ b/src/util/syserror.cpp
@@ -10,6 +10,7 @@
#include <util/syserror.h>
#include <cstring>
+#include <string>
std::string SysErrorString(int err)
{
diff --git a/src/util/system.cpp b/src/util/system.cpp
index 1ae82fbc96..c3c6cbfef6 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -55,13 +55,6 @@
#else
-#ifdef _MSC_VER
-#pragma warning(disable:4786)
-#pragma warning(disable:4804)
-#pragma warning(disable:4805)
-#pragma warning(disable:4717)
-#endif
-
#include <codecvt>
#include <io.h> /* for _commit */
@@ -529,7 +522,7 @@ bool ArgsManager::InitSettings(std::string& error)
bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp, bool backup) const
{
- fs::path settings = GetPathArg("-settings", fs::path{BITCOIN_SETTINGS_FILENAME});
+ fs::path settings = GetPathArg("-settings", BITCOIN_SETTINGS_FILENAME);
if (settings.empty()) {
return false;
}
@@ -610,35 +603,75 @@ bool ArgsManager::IsArgNegated(const std::string& strArg) const
std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault) const
{
+ return GetArg(strArg).value_or(strDefault);
+}
+
+std::optional<std::string> ArgsManager::GetArg(const std::string& strArg) const
+{
const util::SettingsValue value = GetSetting(strArg);
- return SettingToString(value, strDefault);
+ return SettingToString(value);
+}
+
+std::optional<std::string> SettingToString(const util::SettingsValue& value)
+{
+ if (value.isNull()) return std::nullopt;
+ if (value.isFalse()) return "0";
+ if (value.isTrue()) return "1";
+ if (value.isNum()) return value.getValStr();
+ return value.get_str();
}
std::string SettingToString(const util::SettingsValue& value, const std::string& strDefault)
{
- return value.isNull() ? strDefault : value.isFalse() ? "0" : value.isTrue() ? "1" : value.isNum() ? value.getValStr() : value.get_str();
+ return SettingToString(value).value_or(strDefault);
}
int64_t ArgsManager::GetIntArg(const std::string& strArg, int64_t nDefault) const
{
+ return GetIntArg(strArg).value_or(nDefault);
+}
+
+std::optional<int64_t> ArgsManager::GetIntArg(const std::string& strArg) const
+{
const util::SettingsValue value = GetSetting(strArg);
- return SettingToInt(value, nDefault);
+ return SettingToInt(value);
+}
+
+std::optional<int64_t> SettingToInt(const util::SettingsValue& value)
+{
+ if (value.isNull()) return std::nullopt;
+ if (value.isFalse()) return 0;
+ if (value.isTrue()) return 1;
+ if (value.isNum()) return value.getInt<int64_t>();
+ return LocaleIndependentAtoi<int64_t>(value.get_str());
}
int64_t SettingToInt(const util::SettingsValue& value, int64_t nDefault)
{
- return value.isNull() ? nDefault : value.isFalse() ? 0 : value.isTrue() ? 1 : value.isNum() ? value.getInt<int64_t>() : LocaleIndependentAtoi<int64_t>(value.get_str());
+ return SettingToInt(value).value_or(nDefault);
}
bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault) const
{
+ return GetBoolArg(strArg).value_or(fDefault);
+}
+
+std::optional<bool> ArgsManager::GetBoolArg(const std::string& strArg) const
+{
const util::SettingsValue value = GetSetting(strArg);
- return SettingToBool(value, fDefault);
+ return SettingToBool(value);
+}
+
+std::optional<bool> SettingToBool(const util::SettingsValue& value)
+{
+ if (value.isNull()) return std::nullopt;
+ if (value.isBool()) return value.get_bool();
+ return InterpretBool(value.get_str());
}
bool SettingToBool(const util::SettingsValue& value, bool fDefault)
{
- return value.isNull() ? fDefault : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
+ return SettingToBool(value).value_or(fDefault);
}
bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strValue)
@@ -707,7 +740,7 @@ std::string ArgsManager::GetHelpMessage() const
{
const bool show_debug = GetBoolArg("-help-debug", false);
- std::string usage = "";
+ std::string usage;
LOCK(cs_args);
for (const auto& arg_map : m_available_args) {
switch(arg_map.first) {
@@ -798,7 +831,7 @@ std::string HelpMessageOpt(const std::string &option, const std::string &message
std::string("\n\n");
}
-static std::string FormatException(const std::exception* pex, const char* pszThread)
+static std::string FormatException(const std::exception* pex, std::string_view thread_name)
{
#ifdef WIN32
char pszModule[MAX_PATH] = "";
@@ -808,15 +841,15 @@ static std::string FormatException(const std::exception* pex, const char* pszThr
#endif
if (pex)
return strprintf(
- "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
+ "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, thread_name);
else
return strprintf(
- "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
+ "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, thread_name);
}
-void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
+void PrintExceptionContinue(const std::exception* pex, std::string_view thread_name)
{
- std::string message = FormatException(pex, pszThread);
+ std::string message = FormatException(pex, thread_name);
LogPrintf("\n\n************************\n%s\n", message);
tfm::format(std::cerr, "\n\n************************\n%s\n", message);
}
@@ -852,9 +885,9 @@ bool CheckDataDirOption()
return datadir.empty() || fs::is_directory(fs::absolute(datadir));
}
-fs::path GetConfigFile(const std::string& confPath)
+fs::path GetConfigFile(const fs::path& configuration_file_path)
{
- return AbsPathForConfigVal(fs::PathFromString(confPath), false);
+ return AbsPathForConfigVal(configuration_file_path, /*net_specific=*/false);
}
static bool GetConfigOptions(std::istream& stream, const std::string& filepath, std::string& error, std::vector<std::pair<std::string, std::string>>& options, std::list<SectionInfo>& sections)
@@ -938,17 +971,17 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
m_config_sections.clear();
}
- const std::string confPath = GetArg("-conf", BITCOIN_CONF_FILENAME);
- std::ifstream stream{GetConfigFile(confPath)};
+ const fs::path conf_path = GetPathArg("-conf", BITCOIN_CONF_FILENAME);
+ std::ifstream stream{GetConfigFile(conf_path)};
// not ok to have a config file specified that cannot be opened
if (IsArgSet("-conf") && !stream.good()) {
- error = strprintf("specified config file \"%s\" could not be opened.", confPath);
+ error = strprintf("specified config file \"%s\" could not be opened.", fs::PathToString(conf_path));
return false;
}
// ok to not have a config file
if (stream.good()) {
- if (!ReadConfigStream(stream, confPath, error, ignore_invalid_keys)) {
+ if (!ReadConfigStream(stream, fs::PathToString(conf_path), error, ignore_invalid_keys)) {
return false;
}
// `-includeconf` cannot be included in the command line arguments except
@@ -986,7 +1019,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
const size_t default_includes = add_includes({});
for (const std::string& conf_file_name : conf_file_names) {
- std::ifstream conf_file_stream{GetConfigFile(conf_file_name)};
+ std::ifstream conf_file_stream{GetConfigFile(fs::PathFromString(conf_file_name))};
if (conf_file_stream.good()) {
if (!ReadConfigStream(conf_file_stream, conf_file_name, error, ignore_invalid_keys)) {
return false;
diff --git a/src/util/system.h b/src/util/system.h
index 07d7a533aa..c8e1de6700 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -14,7 +14,7 @@
#include <config/bitcoin-config.h>
#endif
-#include <compat.h>
+#include <compat/compat.h>
#include <compat/assumptions.h>
#include <fs.h>
#include <logging.h>
@@ -51,7 +51,7 @@ bool error(const char* fmt, const Args&... args)
return false;
}
-void PrintExceptionContinue(const std::exception *pex, const char* pszThread);
+void PrintExceptionContinue(const std::exception* pex, std::string_view thread_name);
/**
* Ensure file contents are fully committed to disk, using a platform-specific
@@ -97,7 +97,7 @@ bool TryCreateDirectories(const fs::path& p);
fs::path GetDefaultDataDir();
// Return true if -datadir option points to a valid directory or is not specified.
bool CheckDataDirOption();
-fs::path GetConfigFile(const std::string& confPath);
+fs::path GetConfigFile(const fs::path& configuration_file_path);
#ifdef WIN32
fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
@@ -161,8 +161,13 @@ struct SectionInfo
};
std::string SettingToString(const util::SettingsValue&, const std::string&);
+std::optional<std::string> SettingToString(const util::SettingsValue&);
+
int64_t SettingToInt(const util::SettingsValue&, int64_t);
+std::optional<int64_t> SettingToInt(const util::SettingsValue&);
+
bool SettingToBool(const util::SettingsValue&, bool);
+std::optional<bool> SettingToBool(const util::SettingsValue&);
class ArgsManager
{
@@ -335,6 +340,7 @@ protected:
* @return command-line argument or default value
*/
std::string GetArg(const std::string& strArg, const std::string& strDefault) const;
+ std::optional<std::string> GetArg(const std::string& strArg) const;
/**
* Return path argument or default value
@@ -356,6 +362,7 @@ protected:
* @return command-line argument (0 if invalid number) or default value
*/
int64_t GetIntArg(const std::string& strArg, int64_t nDefault) const;
+ std::optional<int64_t> GetIntArg(const std::string& strArg) const;
/**
* Return boolean argument or default value
@@ -365,6 +372,7 @@ protected:
* @return command-line argument or default value
*/
bool GetBoolArg(const std::string& strArg, bool fDefault) const;
+ std::optional<bool> GetBoolArg(const std::string& strArg) const;
/**
* Set an argument if it doesn't already have a value
diff --git a/src/util/thread.cpp b/src/util/thread.cpp
index 14be668685..ae98abdb3d 100644
--- a/src/util/thread.cpp
+++ b/src/util/thread.cpp
@@ -9,10 +9,13 @@
#include <util/threadnames.h>
#include <exception>
+#include <functional>
+#include <string>
+#include <utility>
-void util::TraceThread(const char* thread_name, std::function<void()> thread_func)
+void util::TraceThread(std::string_view thread_name, std::function<void()> thread_func)
{
- util::ThreadRename(thread_name);
+ util::ThreadRename(std::string{thread_name});
try {
LogPrintf("%s thread start\n", thread_name);
thread_func();
diff --git a/src/util/thread.h b/src/util/thread.h
index ca2eccc0c3..b80bf046a0 100644
--- a/src/util/thread.h
+++ b/src/util/thread.h
@@ -6,12 +6,13 @@
#define BITCOIN_UTIL_THREAD_H
#include <functional>
+#include <string>
namespace util {
/**
* A wrapper for do-something-once thread functions.
*/
-void TraceThread(const char* thread_name, std::function<void()> thread_func);
+void TraceThread(std::string_view thread_name, std::function<void()> thread_func);
} // namespace util
diff --git a/src/util/time.cpp b/src/util/time.cpp
index 7d9d6bcff1..f6d37347f8 100644
--- a/src/util/time.cpp
+++ b/src/util/time.cpp
@@ -7,17 +7,20 @@
#include <config/bitcoin-config.h>
#endif
-#include <compat.h>
+#include <compat/compat.h>
+#include <tinyformat.h>
#include <util/time.h>
-
#include <util/check.h>
-#include <atomic>
#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <atomic>
+#include <chrono>
#include <ctime>
+#include <locale>
#include <thread>
-
-#include <tinyformat.h>
+#include <sstream>
+#include <string>
void UninterruptibleSleep(const std::chrono::microseconds& n) { std::this_thread::sleep_for(n); }
diff --git a/src/util/time.h b/src/util/time.h
index ad91a72860..4f9bde5d56 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -6,10 +6,10 @@
#ifndef BITCOIN_UTIL_TIME_H
#define BITCOIN_UTIL_TIME_H
-#include <compat.h>
+#include <compat/compat.h>
#include <chrono>
-#include <stdint.h>
+#include <cstdint>
#include <string>
using namespace std::chrono_literals;
@@ -24,6 +24,7 @@ struct NodeClock : public std::chrono::system_clock {
};
using NodeSeconds = std::chrono::time_point<NodeClock, std::chrono::seconds>;
+using SteadyClock = std::chrono::steady_clock;
using SteadySeconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::seconds>;
using SteadyMilliseconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::milliseconds>;
using SteadyMicroseconds = std::chrono::time_point<std::chrono::steady_clock, std::chrono::microseconds>;
@@ -40,23 +41,24 @@ void UninterruptibleSleep(const std::chrono::microseconds& n);
* This helper is used to convert durations/time_points before passing them over an
* interface that doesn't support std::chrono (e.g. RPC, debug log, or the GUI)
*/
+template <typename Dur1, typename Dur2>
+constexpr auto Ticks(Dur2 d)
+{
+ return std::chrono::duration_cast<Dur1>(d).count();
+}
template <typename Duration, typename Timepoint>
constexpr auto TicksSinceEpoch(Timepoint t)
{
- return std::chrono::time_point_cast<Duration>(t).time_since_epoch().count();
+ return Ticks<Duration>(t.time_since_epoch());
}
constexpr int64_t count_seconds(std::chrono::seconds t) { return t.count(); }
constexpr int64_t count_milliseconds(std::chrono::milliseconds t) { return t.count(); }
constexpr int64_t count_microseconds(std::chrono::microseconds t) { return t.count(); }
+using HoursDouble = std::chrono::duration<double, std::chrono::hours::period>;
using SecondsDouble = std::chrono::duration<double, std::chrono::seconds::period>;
/**
- * Helper to count the seconds in any std::chrono::duration type
- */
-inline double CountSecondsDouble(SecondsDouble t) { return t.count(); }
-
-/**
* DEPRECATED
* Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
* ClockType is
diff --git a/src/util/translation.h b/src/util/translation.h
index aee601d9c1..07b7f43c8a 100644
--- a/src/util/translation.h
+++ b/src/util/translation.h
@@ -6,7 +6,9 @@
#define BITCOIN_UTIL_TRANSLATION_H
#include <tinyformat.h>
+
#include <functional>
+#include <string>
/**
* Bilingual messages:
diff --git a/src/util/url.cpp b/src/util/url.cpp
index e42d93bce8..ea9323e666 100644
--- a/src/util/url.cpp
+++ b/src/util/url.cpp
@@ -5,7 +5,8 @@
#include <util/url.h>
#include <event2/http.h>
-#include <stdlib.h>
+
+#include <cstdlib>
#include <string>
std::string urlDecode(const std::string &urlEncoded) {
diff --git a/src/util/vector.h b/src/util/vector.h
index dab65ded2a..ed745affe5 100644
--- a/src/util/vector.h
+++ b/src/util/vector.h
@@ -7,6 +7,7 @@
#include <initializer_list>
#include <type_traits>
+#include <utility>
#include <vector>
/** Construct a vector with the specified elements.
diff --git a/src/validation.cpp b/src/validation.cpp
index b775c85912..fb29ca3ae7 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -5,6 +5,9 @@
#include <validation.h>
+#include <kernel/coinstats.h>
+#include <kernel/mempool_persist.h>
+
#include <arith_uint256.h>
#include <chain.h>
#include <chainparams.h>
@@ -17,8 +20,8 @@
#include <consensus/validation.h>
#include <cuckoocache.h>
#include <flatfile.h>
+#include <fs.h>
#include <hash.h>
-#include <kernel/coinstats.h>
#include <logging.h>
#include <logging/timer.h>
#include <node/blockstorage.h>
@@ -47,12 +50,15 @@
#include <util/rbf.h>
#include <util/strencodings.h>
#include <util/system.h>
+#include <util/time.h>
#include <util/trace.h>
#include <util/translation.h>
#include <validationinterface.h>
#include <warnings.h>
#include <algorithm>
+#include <cassert>
+#include <chrono>
#include <deque>
#include <numeric>
#include <optional>
@@ -61,8 +67,9 @@
using kernel::CCoinsStats;
using kernel::CoinStatsHashType;
using kernel::ComputeUTXOStats;
+using kernel::LoadMempool;
-using node::BLOCKFILE_CHUNK_SIZE;
+using fsbridge::FopenFn;
using node::BlockManager;
using node::BlockMap;
using node::CBlockIndexHeightOnlyComparator;
@@ -70,11 +77,8 @@ using node::CBlockIndexWorkComparator;
using node::fImporting;
using node::fPruneMode;
using node::fReindex;
-using node::nPruneTarget;
-using node::OpenBlockFile;
using node::ReadBlockFromDisk;
using node::SnapshotMetadata;
-using node::UNDOFILE_CHUNK_SIZE;
using node::UndoReadFromDisk;
using node::UnlinkPrunedFiles;
@@ -120,7 +124,6 @@ GlobalMutex g_best_block_mutex;
std::condition_variable g_best_block_cv;
uint256 g_best_block;
bool g_parallel_script_checks{false};
-bool fRequireStandard = true;
bool fCheckBlockIndex = false;
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
@@ -128,7 +131,7 @@ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
uint256 hashAssumeValid;
arith_uint256 nMinimumChainWork;
-const CBlockIndex* CChainState::FindForkInGlobalIndex(const CBlockLocator& locator) const
+const CBlockIndex* Chainstate::FindForkInGlobalIndex(const CBlockLocator& locator) const
{
AssertLockHeld(cs_main);
@@ -154,10 +157,9 @@ bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
std::vector<CScriptCheck>* pvChecks = nullptr)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction& tx)
+bool CheckFinalTxAtTip(const CBlockIndex& active_chain_tip, const CTransaction& tx)
{
AssertLockHeld(cs_main);
- assert(active_chain_tip); // TODO: Make active_chain_tip a reference
// CheckFinalTxAtTip() uses active_chain_tip.Height()+1 to evaluate
// nLockTime because when IsFinalTx() is called within
@@ -165,14 +167,14 @@ bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction&
// evaluated is what is used. Thus if we want to know if a
// transaction can be part of the *next* block, we need to call
// IsFinalTx() with one more than active_chain_tip.Height().
- const int nBlockHeight = active_chain_tip->nHeight + 1;
+ const int nBlockHeight = active_chain_tip.nHeight + 1;
// BIP113 requires that time-locked transactions have nLockTime set to
// less than the median time of the previous block they're contained in.
// When the next block is created its previous block will be the current
// chain tip, so we use that to calculate the median time passed to
// IsFinalTx().
- const int64_t nBlockTime{active_chain_tip->GetMedianTimePast()};
+ const int64_t nBlockTime{active_chain_tip.GetMedianTimePast()};
return IsFinalTx(tx, nBlockHeight, nBlockTime);
}
@@ -255,23 +257,23 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
// Returns the script flags which should be checked for a given block
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
-static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age)
+static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
{
AssertLockHeld(::cs_main);
AssertLockHeld(pool.cs);
- int expired = pool.Expire(GetTime<std::chrono::seconds>() - age);
+ int expired = pool.Expire(GetTime<std::chrono::seconds>() - pool.m_expiry);
if (expired != 0) {
LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired);
}
std::vector<COutPoint> vNoSpendsRemaining;
- pool.TrimToSize(limit, &vNoSpendsRemaining);
+ pool.TrimToSize(pool.m_max_size_bytes, &vNoSpendsRemaining);
for (const COutPoint& removed : vNoSpendsRemaining)
coins_cache.Uncache(removed);
}
-static bool IsCurrentForFeeEstimation(CChainState& active_chainstate) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
+static bool IsCurrentForFeeEstimation(Chainstate& active_chainstate) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
AssertLockHeld(cs_main);
if (active_chainstate.IsInitialBlockDownload())
@@ -284,7 +286,7 @@ static bool IsCurrentForFeeEstimation(CChainState& active_chainstate) EXCLUSIVE_
return true;
}
-void CChainState::MaybeUpdateMempoolForReorg(
+void Chainstate::MaybeUpdateMempoolForReorg(
DisconnectedBlockTransactions& disconnectpool,
bool fAddToMempool)
{
@@ -320,9 +322,7 @@ void CChainState::MaybeUpdateMempoolForReorg(
// previously-confirmed transactions back to the mempool.
// UpdateTransactionsFromBlock finds descendants of any transactions in
// the disconnectpool that were added back and cleans up the mempool state.
- const uint64_t ancestor_count_limit = gArgs.GetIntArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT);
- const uint64_t ancestor_size_limit = gArgs.GetIntArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * 1000;
- m_mempool->UpdateTransactionsFromBlock(vHashUpdate, ancestor_size_limit, ancestor_count_limit);
+ m_mempool->UpdateTransactionsFromBlock(vHashUpdate);
// Predicate to use for filtering transactions in removeForReorg.
// Checks whether the transaction is still final and, if it spends a coinbase output, mature.
@@ -336,7 +336,7 @@ void CChainState::MaybeUpdateMempoolForReorg(
const CTransaction& tx = it->GetTx();
// The transaction must be final.
- if (!CheckFinalTxAtTip(m_chain.Tip(), tx)) return true;
+ if (!CheckFinalTxAtTip(*Assert(m_chain.Tip()), tx)) return true;
LockPoints lp = it->GetLockPoints();
const bool validLP{TestLockPointValidity(m_chain, lp)};
CCoinsViewMemPool view_mempool(&CoinsTip(), *m_mempool);
@@ -374,11 +374,7 @@ void CChainState::MaybeUpdateMempoolForReorg(
// We also need to remove any now-immature transactions
m_mempool->removeForReorg(m_chain, filter_final_and_mature);
// Re-limit mempool size, in case we added any transactions
- LimitMempoolSize(
- *m_mempool,
- this->CoinsTip(),
- gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000,
- std::chrono::hours{gArgs.GetIntArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
+ LimitMempoolSize(*m_mempool, this->CoinsTip());
}
/**
@@ -428,11 +424,11 @@ namespace {
class MemPoolAccept
{
public:
- explicit MemPoolAccept(CTxMemPool& mempool, CChainState& active_chainstate) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&active_chainstate.CoinsTip(), m_pool), m_active_chainstate(active_chainstate),
- m_limit_ancestors(gArgs.GetIntArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT)),
- m_limit_ancestor_size(gArgs.GetIntArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000),
- m_limit_descendants(gArgs.GetIntArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)),
- m_limit_descendant_size(gArgs.GetIntArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000) {
+ explicit MemPoolAccept(CTxMemPool& mempool, Chainstate& active_chainstate) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&active_chainstate.CoinsTip(), m_pool), m_active_chainstate(active_chainstate),
+ m_limit_ancestors(m_pool.m_limits.ancestor_count),
+ m_limit_ancestor_size(m_pool.m_limits.ancestor_size_vbytes),
+ m_limit_descendants(m_pool.m_limits.descendant_count),
+ m_limit_descendant_size(m_pool.m_limits.descendant_size_vbytes) {
}
// We put the arguments we're handed into a struct, so we can pass them
@@ -453,7 +449,7 @@ public:
/** Whether we allow transactions to replace mempool transactions by BIP125 rules. If false,
* any transaction spending the same inputs as a transaction in the mempool is considered
* a conflict. */
- const bool m_allow_bip125_replacement;
+ const bool m_allow_replacement;
/** When true, the mempool will not be trimmed when individual transactions are submitted in
* Finalize(). Instead, limits should be enforced at the end to ensure the package is not
* partially submitted.
@@ -473,7 +469,7 @@ public:
/* m_bypass_limits */ bypass_limits,
/* m_coins_to_uncache */ coins_to_uncache,
/* m_test_accept */ test_accept,
- /* m_allow_bip125_replacement */ true,
+ /* m_allow_replacement */ true,
/* m_package_submission */ false,
/* m_package_feerates */ false,
};
@@ -487,7 +483,7 @@ public:
/* m_bypass_limits */ false,
/* m_coins_to_uncache */ coins_to_uncache,
/* m_test_accept */ true,
- /* m_allow_bip125_replacement */ false,
+ /* m_allow_replacement */ false,
/* m_package_submission */ false, // not submitting to mempool
/* m_package_feerates */ false,
};
@@ -501,7 +497,7 @@ public:
/* m_bypass_limits */ false,
/* m_coins_to_uncache */ coins_to_uncache,
/* m_test_accept */ false,
- /* m_allow_bip125_replacement */ false,
+ /* m_allow_replacement */ false,
/* m_package_submission */ true,
/* m_package_feerates */ true,
};
@@ -514,7 +510,7 @@ public:
/* m_bypass_limits */ false,
/* m_coins_to_uncache */ package_args.m_coins_to_uncache,
/* m_test_accept */ package_args.m_test_accept,
- /* m_allow_bip125_replacement */ true,
+ /* m_allow_replacement */ true,
/* m_package_submission */ false,
/* m_package_feerates */ false, // only 1 transaction
};
@@ -528,7 +524,7 @@ public:
bool bypass_limits,
std::vector<COutPoint>& coins_to_uncache,
bool test_accept,
- bool allow_bip125_replacement,
+ bool allow_replacement,
bool package_submission,
bool package_feerates)
: m_chainparams{chainparams},
@@ -536,7 +532,7 @@ public:
m_bypass_limits{bypass_limits},
m_coins_to_uncache{coins_to_uncache},
m_test_accept{test_accept},
- m_allow_bip125_replacement{allow_bip125_replacement},
+ m_allow_replacement{allow_replacement},
m_package_submission{package_submission},
m_package_feerates{package_feerates}
{
@@ -644,13 +640,14 @@ private:
{
AssertLockHeld(::cs_main);
AssertLockHeld(m_pool.cs);
- CAmount mempoolRejectFee = m_pool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(package_size);
+ CAmount mempoolRejectFee = m_pool.GetMinFee().GetFee(package_size);
if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
}
- if (package_fee < ::minRelayTxFee.GetFee(package_size)) {
- return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met", strprintf("%d < %d", package_fee, ::minRelayTxFee.GetFee(package_size)));
+ if (package_fee < m_pool.m_min_relay_feerate.GetFee(package_size)) {
+ return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
+ strprintf("%d < %d", package_fee, m_pool.m_min_relay_feerate.GetFee(package_size)));
}
return true;
}
@@ -661,7 +658,7 @@ private:
CCoinsViewMemPool m_viewmempool;
CCoinsView m_dummy;
- CChainState& m_active_chainstate;
+ Chainstate& m_active_chainstate;
// The package limits in effect at the time of invocation.
const size_t m_limit_ancestors;
@@ -702,8 +699,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
std::string reason;
- if (fRequireStandard && !IsStandardTx(tx, reason))
+ if (m_pool.m_require_standard && !IsStandardTx(tx, m_pool.m_max_datacarrier_bytes, m_pool.m_permit_bare_multisig, m_pool.m_dust_relay_feerate, reason)) {
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
+ }
// Do not work on transactions that are too small.
// A transaction with 1 segwit input and 1 P2WPHK output has non-witness size of 82 bytes.
@@ -715,7 +713,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
- if (!CheckFinalTxAtTip(m_active_chainstate.m_chain.Tip(), tx)) {
+ if (!CheckFinalTxAtTip(*Assert(m_active_chainstate.m_chain.Tip()), tx)) {
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
}
@@ -733,7 +731,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
{
const CTransaction* ptxConflicting = m_pool.GetConflictTx(txin.prevout);
if (ptxConflicting) {
- if (!args.m_allow_bip125_replacement) {
+ if (!args.m_allow_replacement) {
// Transaction conflicts with a mempool tx, but we're not allowing replacements.
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "bip125-replacement-disallowed");
}
@@ -746,7 +744,10 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Applications relying on first-seen mempool behavior should
// check all unconfirmed ancestors; otherwise an opt-in ancestor
// might be replaced, causing removal of this descendant.
- if (!SignalsOptInRBF(*ptxConflicting)) {
+ //
+ // If replaceability signaling is ignored due to node setting,
+ // replacement is always allowed.
+ if (!m_pool.m_full_rbf && !SignalsOptInRBF(*ptxConflicting)) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "txn-mempool-conflict");
}
@@ -806,13 +807,14 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return false; // state filled in by CheckTxInputs
}
- if (fRequireStandard && !AreInputsStandard(tx, m_view)) {
+ if (m_pool.m_require_standard && !AreInputsStandard(tx, m_view)) {
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
}
// Check for non-standard witnesses.
- if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, m_view))
+ if (tx.HasWitness() && m_pool.m_require_standard && !IsWitnessStandard(tx, m_view)) {
return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");
+ }
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
@@ -839,7 +841,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
strprintf("%d", nSigOpsCost));
- // No individual transactions are allowed below minRelayTxFee and mempool min fee except from
+ // No individual transactions are allowed below the min relay feerate and mempool min feerate except from
// disconnected blocks and transactions in a package. Package transactions will be checked using
// package feerate later.
if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state)) return false;
@@ -859,8 +861,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
// Specifically, the subset of RBF transactions which we allow despite chain limits are those which
// conflict directly with exactly one other transaction (but may evict children of said transaction),
// and which are not adding any new mempool dependencies. Note that the "no new mempool dependencies"
- // check is accomplished later, so we don't bother doing anything about it here, but if BIP 125 is
- // amended, we may need to move that check to here instead of removing it wholesale.
+ // check is accomplished later, so we don't bother doing anything about it here, but if our
+ // policy changes, we may need to move that check to here instead of removing it wholesale.
//
// Such transactions are clearly not merging any existing packages, so we are only concerned with
// ensuring that (a) no package is growing past the package size (not count) limits and (b) we are
@@ -927,7 +929,7 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
TxValidationState& state = ws.m_state;
CFeeRate newFeeRate(ws.m_modified_fees, ws.m_vsize);
- // The replacement transaction must have a higher feerate than its direct conflicts.
+ // Enforce Rule #6. The replacement transaction must have a higher feerate than its direct conflicts.
// - The motivation for this check is to ensure that the replacement transaction is preferable for
// block-inclusion, compared to what would be removed from the mempool.
// - This logic predates ancestor feerate-based transaction selection, which is why it doesn't
@@ -940,24 +942,24 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
}
- // Calculate all conflicting entries and enforce BIP125 Rule #5.
+ // Calculate all conflicting entries and enforce Rule #5.
if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, ws.m_all_conflicting)}) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
"too many potential replacements", *err_string);
}
- // Enforce BIP125 Rule #2.
+ // Enforce Rule #2.
if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, ws.m_iters_conflicting)}) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
"replacement-adds-unconfirmed", *err_string);
}
// Check if it's economically rational to mine this transaction rather than the ones it
- // replaces and pays for its own relay fees. Enforce BIP125 Rules #3 and #4.
+ // replaces and pays for its own relay fees. Enforce Rules #3 and #4.
for (CTxMemPool::txiter it : ws.m_all_conflicting) {
ws.m_conflicting_fees += it->GetModifiedFee();
ws.m_conflicting_size += it->GetTxSize();
}
if (const auto err_string{PaysForRBF(ws.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
- ::incrementalRelayFee, hash)}) {
+ m_pool.m_incremental_relay_feerate, hash)}) {
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "insufficient fee", *err_string);
}
return true;
@@ -1082,7 +1084,7 @@ bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
// in the package. LimitMempoolSize() should be called at the very end to make sure the mempool
// is still within limits and package submission happens atomically.
if (!args.m_package_submission && !bypass_limits) {
- LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip(), gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, std::chrono::hours{gArgs.GetIntArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
+ LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
if (!m_pool.exists(GenTxid::Txid(hash)))
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool full");
}
@@ -1147,9 +1149,7 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
// It may or may not be the case that all the transactions made it into the mempool. Regardless,
// make sure we haven't exceeded max mempool size.
- LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip(),
- gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000,
- std::chrono::hours{gArgs.GetIntArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY)});
+ LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
// Find the wtxids of the transactions that made it into the mempool. Allow partial submission,
// but don't report success unless they all made it into the mempool.
@@ -1224,7 +1224,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
// package to spend. Since we already checked conflicts in the package and we don't allow
// replacements, we don't need to track the coins spent. Note that this logic will need to be
// updated if package replace-by-fee is allowed in the future.
- assert(!args.m_allow_bip125_replacement);
+ assert(!args.m_allow_replacement);
m_viewmempool.PackageAddTransaction(ws.m_ptx);
}
@@ -1411,7 +1411,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
} // anon namespace
-MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, const CTransactionRef& tx,
+MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,
int64_t accept_time, bool bypass_limits, bool test_accept)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
@@ -1438,7 +1438,7 @@ MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, const CTr
return result;
}
-PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTxMemPool& pool,
+PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,
const Package& package, bool test_accept)
{
AssertLockHeld(cs_main);
@@ -1497,7 +1497,7 @@ void CoinsViews::InitCache()
m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
}
-CChainState::CChainState(
+Chainstate::Chainstate(
CTxMemPool* mempool,
BlockManager& blockman,
ChainstateManager& chainman,
@@ -1508,7 +1508,7 @@ CChainState::CChainState(
m_chainman(chainman),
m_from_snapshot_blockhash(from_snapshot_blockhash) {}
-void CChainState::InitCoinsDB(
+void Chainstate::InitCoinsDB(
size_t cache_size_bytes,
bool in_memory,
bool should_wipe,
@@ -1522,7 +1522,7 @@ void CChainState::InitCoinsDB(
leveldb_name, cache_size_bytes, in_memory, should_wipe);
}
-void CChainState::InitCoinsCache(size_t cache_size_bytes)
+void Chainstate::InitCoinsCache(size_t cache_size_bytes)
{
AssertLockHeld(::cs_main);
assert(m_coins_views != nullptr);
@@ -1532,10 +1532,10 @@ void CChainState::InitCoinsCache(size_t cache_size_bytes)
// Note that though this is marked const, we may end up modifying `m_cached_finished_ibd`, which
// is a performance-related implementation detail. This function must be marked
-// `const` so that `CValidationInterface` clients (which are given a `const CChainState*`)
+// `const` so that `CValidationInterface` clients (which are given a `const Chainstate*`)
// can call it.
//
-bool CChainState::IsInitialBlockDownload() const
+bool Chainstate::IsInitialBlockDownload() const
{
// Optimization: pre-test latch before taking the lock.
if (m_cached_finished_ibd.load(std::memory_order_relaxed))
@@ -1577,7 +1577,7 @@ static void AlertNotify(const std::string& strMessage)
#endif
}
-void CChainState::CheckForkWarningConditions()
+void Chainstate::CheckForkWarningConditions()
{
AssertLockHeld(cs_main);
@@ -1596,7 +1596,7 @@ void CChainState::CheckForkWarningConditions()
}
// Called both upon regular invalid block discovery *and* InvalidateBlock
-void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
+void Chainstate::InvalidChainFound(CBlockIndex* pindexNew)
{
AssertLockHeld(cs_main);
if (!m_chainman.m_best_invalid || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork) {
@@ -1619,7 +1619,7 @@ void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
// Same as InvalidChainFound, above, except not called directly from InvalidateBlock,
// which does its own setBlockIndexCandidates management.
-void CChainState::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state)
+void Chainstate::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state)
{
AssertLockHeld(cs_main);
if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {
@@ -1655,7 +1655,8 @@ bool CScriptCheck::operator()() {
static CuckooCache::cache<uint256, SignatureCacheHasher> g_scriptExecutionCache;
static CSHA256 g_scriptExecutionCacheHasher;
-void InitScriptExecutionCache() {
+bool InitScriptExecutionCache(size_t max_size_bytes)
+{
// Setup the salted hasher
uint256 nonce = GetRandHash();
// We want the nonce to be 64 bytes long to force the hasher to process
@@ -1663,12 +1664,14 @@ void InitScriptExecutionCache() {
// just write our 32-byte entropy twice to fill the 64 bytes.
g_scriptExecutionCacheHasher.Write(nonce.begin(), 32);
g_scriptExecutionCacheHasher.Write(nonce.begin(), 32);
- // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero,
- // setup_bytes creates the minimum possible cache (2 elements).
- size_t nMaxCacheSize = std::min(std::max((int64_t)0, gArgs.GetIntArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE) / 2), MAX_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20);
- size_t nElems = g_scriptExecutionCache.setup_bytes(nMaxCacheSize);
- LogPrintf("Using %zu MiB out of %zu/2 requested for script execution cache, able to store %zu elements\n",
- (nElems*sizeof(uint256)) >>20, (nMaxCacheSize*2)>>20, nElems);
+
+ auto setup_results = g_scriptExecutionCache.setup_bytes(max_size_bytes);
+ if (!setup_results) return false;
+
+ const auto [num_elems, approx_size_bytes] = *setup_results;
+ LogPrintf("Using %zu MiB out of %zu MiB requested for script execution cache, able to store %zu elements\n",
+ approx_size_bytes >> 20, max_size_bytes >> 20, num_elems);
+ return true;
}
/**
@@ -1821,7 +1824,7 @@ int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out)
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
* When FAILED is returned, view is left in an indeterminate state. */
-DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
+DisconnectResult Chainstate::DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
{
AssertLockHeld(::cs_main);
bool fClean = true;
@@ -1974,7 +1977,7 @@ static int64_t nBlocksTotal = 0;
/** Apply the effects of this block (with given index) on the UTXO set represented by coins.
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
* can fail if those validity checks fail (among other reasons). */
-bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, CBlockIndex* pindex,
+bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state, CBlockIndex* pindex,
CCoinsViewCache& view, bool fJustCheck)
{
AssertLockHeld(cs_main);
@@ -2268,7 +2271,6 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
m_blockman.m_dirty_blockindex.insert(pindex);
}
- assert(pindex->phashBlock);
// add this block to the view's block chain
view.SetBestBlock(pindex->GetBlockHash());
@@ -2287,15 +2289,15 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
return true;
}
-CoinsCacheSizeState CChainState::GetCoinsCacheSizeState()
+CoinsCacheSizeState Chainstate::GetCoinsCacheSizeState()
{
AssertLockHeld(::cs_main);
return this->GetCoinsCacheSizeState(
m_coinstip_cache_size_bytes,
- gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
+ m_mempool ? m_mempool->m_max_size_bytes : 0);
}
-CoinsCacheSizeState CChainState::GetCoinsCacheSizeState(
+CoinsCacheSizeState Chainstate::GetCoinsCacheSizeState(
size_t max_coins_cache_size_bytes,
size_t max_mempool_size_bytes)
{
@@ -2319,7 +2321,7 @@ CoinsCacheSizeState CChainState::GetCoinsCacheSizeState(
return CoinsCacheSizeState::OK;
}
-bool CChainState::FlushStateToDisk(
+bool Chainstate::FlushStateToDisk(
BlockValidationState &state,
FlushStateMode mode,
int nManualPruneHeight)
@@ -2462,7 +2464,7 @@ bool CChainState::FlushStateToDisk(
return true;
}
-void CChainState::ForceFlushStateToDisk()
+void Chainstate::ForceFlushStateToDisk()
{
BlockValidationState state;
if (!this->FlushStateToDisk(state, FlushStateMode::ALWAYS)) {
@@ -2470,7 +2472,7 @@ void CChainState::ForceFlushStateToDisk()
}
}
-void CChainState::PruneAndFlush()
+void Chainstate::PruneAndFlush()
{
BlockValidationState state;
m_blockman.m_check_for_pruning = true;
@@ -2517,7 +2519,7 @@ static void UpdateTipLog(
!warning_messages.empty() ? strprintf(" warning='%s'", warning_messages) : "");
}
-void CChainState::UpdateTip(const CBlockIndex* pindexNew)
+void Chainstate::UpdateTip(const CBlockIndex* pindexNew)
{
AssertLockHeld(::cs_main);
const auto& coins_tip = this->CoinsTip();
@@ -2573,13 +2575,14 @@ void CChainState::UpdateTip(const CBlockIndex* pindexNew)
* disconnectpool (note that the caller is responsible for mempool consistency
* in any case).
*/
-bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTransactions* disconnectpool)
+bool Chainstate::DisconnectTip(BlockValidationState& state, DisconnectedBlockTransactions* disconnectpool)
{
AssertLockHeld(cs_main);
if (m_mempool) AssertLockHeld(m_mempool->cs);
CBlockIndex *pindexDelete = m_chain.Tip();
assert(pindexDelete);
+ assert(pindexDelete->pprev);
// Read block from disk.
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
CBlock& block = *pblock;
@@ -2627,7 +2630,7 @@ bool CChainState::DisconnectTip(BlockValidationState& state, DisconnectedBlockTr
}
}
- m_chain.SetTip(pindexDelete->pprev);
+ m_chain.SetTip(*pindexDelete->pprev);
UpdateTip(pindexDelete->pprev);
// Let wallets know transactions went from 1-confirmed to
@@ -2688,7 +2691,7 @@ public:
*
* The block is added to connectTrace if connection succeeds.
*/
-bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions& disconnectpool)
+bool Chainstate::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions& disconnectpool)
{
AssertLockHeld(cs_main);
if (m_mempool) AssertLockHeld(m_mempool->cs);
@@ -2741,7 +2744,7 @@ bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew
disconnectpool.removeForBlock(blockConnecting.vtx);
}
// Update m_chain & related variables.
- m_chain.SetTip(pindexNew);
+ m_chain.SetTip(*pindexNew);
UpdateTip(pindexNew);
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
@@ -2756,7 +2759,7 @@ bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew
* Return the tip of the chain with the most work in it, that isn't
* known to be invalid (it's however far from certain to be valid).
*/
-CBlockIndex* CChainState::FindMostWorkChain()
+CBlockIndex* Chainstate::FindMostWorkChain()
{
AssertLockHeld(::cs_main);
do {
@@ -2815,7 +2818,7 @@ CBlockIndex* CChainState::FindMostWorkChain()
}
/** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
-void CChainState::PruneBlockIndexCandidates() {
+void Chainstate::PruneBlockIndexCandidates() {
// Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails.
std::set<CBlockIndex*, CBlockIndexWorkComparator>::iterator it = setBlockIndexCandidates.begin();
@@ -2832,7 +2835,7 @@ void CChainState::PruneBlockIndexCandidates() {
*
* @returns true unless a system error occurred
*/
-bool CChainState::ActivateBestChainStep(BlockValidationState& state, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace)
+bool Chainstate::ActivateBestChainStep(BlockValidationState& state, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace)
{
AssertLockHeld(cs_main);
if (m_mempool) AssertLockHeld(m_mempool->cs);
@@ -2924,7 +2927,7 @@ static SynchronizationState GetSynchronizationState(bool init)
return SynchronizationState::INIT_DOWNLOAD;
}
-static bool NotifyHeaderTip(CChainState& chainstate) LOCKS_EXCLUDED(cs_main) {
+static bool NotifyHeaderTip(Chainstate& chainstate) LOCKS_EXCLUDED(cs_main) {
bool fNotify = false;
bool fInitialBlockDownload = false;
static CBlockIndex* pindexHeaderOld = nullptr;
@@ -2941,7 +2944,7 @@ static bool NotifyHeaderTip(CChainState& chainstate) LOCKS_EXCLUDED(cs_main) {
}
// Send block tip changed notifications without cs_main
if (fNotify) {
- uiInterface.NotifyHeaderTip(GetSynchronizationState(fInitialBlockDownload), pindexHeader);
+ uiInterface.NotifyHeaderTip(GetSynchronizationState(fInitialBlockDownload), pindexHeader->nHeight, pindexHeader->nTime, false);
}
return fNotify;
}
@@ -2954,7 +2957,7 @@ static void LimitValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main) {
}
}
-bool CChainState::ActivateBestChain(BlockValidationState& state, std::shared_ptr<const CBlock> pblock)
+bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<const CBlock> pblock)
{
AssertLockNotHeld(m_chainstate_mutex);
@@ -3056,7 +3059,7 @@ bool CChainState::ActivateBestChain(BlockValidationState& state, std::shared_ptr
return true;
}
-bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
+bool Chainstate::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
{
AssertLockNotHeld(m_chainstate_mutex);
AssertLockNotHeld(::cs_main);
@@ -3087,7 +3090,7 @@ bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex
return ActivateBestChain(state, std::shared_ptr<const CBlock>());
}
-bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex)
+bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex)
{
AssertLockNotHeld(m_chainstate_mutex);
AssertLockNotHeld(::cs_main);
@@ -3230,7 +3233,7 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pind
return true;
}
-void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
+void Chainstate::ResetBlockFailureFlags(CBlockIndex *pindex) {
AssertLockHeld(cs_main);
int nHeight = pindex->nHeight;
@@ -3263,7 +3266,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
}
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
-void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos)
+void Chainstate::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos)
{
AssertLockHeld(cs_main);
pindexNew->nTx = block.vtx.size();
@@ -3429,6 +3432,22 @@ std::vector<unsigned char> ChainstateManager::GenerateCoinbaseCommitment(CBlock&
return commitment;
}
+bool HasValidProofOfWork(const std::vector<CBlockHeader>& headers, const Consensus::Params& consensusParams)
+{
+ return std::all_of(headers.cbegin(), headers.cend(),
+ [&](const auto& header) { return CheckProofOfWork(header.GetHash(), header.nBits, consensusParams);});
+}
+
+arith_uint256 CalculateHeadersWork(const std::vector<CBlockHeader>& headers)
+{
+ arith_uint256 total_work{0};
+ for (const CBlockHeader& header : headers) {
+ CBlockIndex dummy(header);
+ total_work += GetBlockProof(dummy);
+ }
+ return total_work;
+}
+
/** Context-dependent validity checks.
* By "context", we mean only the previous block headers, but not the UTXO
* set; UTXO-related validity checks are done in ConnectBlock().
@@ -3438,7 +3457,7 @@ std::vector<unsigned char> ChainstateManager::GenerateCoinbaseCommitment(CBlock&
* in ConnectBlock().
* Note that -reindex-chainstate skips the validation that happens here!
*/
-static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const ChainstateManager& chainman, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
+static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const ChainstateManager& chainman, const CBlockIndex* pindexPrev, NodeClock::time_point now) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
AssertLockHeld(::cs_main);
assert(pindexPrev != nullptr);
@@ -3466,8 +3485,9 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio
return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, "time-too-old", "block's timestamp is too early");
// Check timestamp
- if (block.GetBlockTime() > nAdjustedTime + MAX_FUTURE_BLOCK_TIME)
+ if (block.Time() > now + std::chrono::seconds{MAX_FUTURE_BLOCK_TIME}) {
return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "time-too-new", "block timestamp too far in the future");
+ }
// Reject blocks with outdated version
if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_HEIGHTINCB)) ||
@@ -3491,15 +3511,15 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
const int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1;
// Enforce BIP113 (Median Time Past).
- int nLockTimeFlags = 0;
+ bool enforce_locktime_median_time_past{false};
if (DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_CSV)) {
assert(pindexPrev != nullptr);
- nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
+ enforce_locktime_median_time_past = true;
}
- int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
- ? pindexPrev->GetMedianTimePast()
- : block.GetBlockTime();
+ const int64_t nLockTimeCutoff{enforce_locktime_median_time_past ?
+ pindexPrev->GetMedianTimePast() :
+ block.GetBlockTime()};
// Check that all transactions are finalized
for (const auto& tx : block.vtx) {
@@ -3568,9 +3588,10 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
return true;
}
-bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, CBlockIndex** ppindex)
+bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, CBlockIndex** ppindex, bool min_pow_checked)
{
AssertLockHeld(cs_main);
+
// Check for duplicate
uint256 hash = block.GetHash();
BlockMap::iterator miSelf{m_blockman.m_block_index.find(hash)};
@@ -3604,7 +3625,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
LogPrint(BCLog::VALIDATION, "%s: %s prev block invalid\n", __func__, hash.ToString());
return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk");
}
- if (!ContextualCheckBlockHeader(block, state, m_blockman, *this, pindexPrev, m_adjusted_time_callback())) {
+ if (!ContextualCheckBlockHeader(block, state, m_blockman, *this, pindexPrev, m_options.adjusted_time_callback())) {
LogPrint(BCLog::VALIDATION, "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString());
return false;
}
@@ -3648,6 +3669,10 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
}
}
}
+ if (!min_pow_checked) {
+ LogPrint(BCLog::VALIDATION, "%s: not adding new block header %s, missing anti-dos proof-of-work validation\n", __func__, hash.ToString());
+ return state.Invalid(BlockValidationResult::BLOCK_HEADER_LOW_WORK, "too-little-chainwork");
+ }
CBlockIndex* pindex{m_blockman.AddToBlockIndex(block, m_best_header)};
if (ppindex)
@@ -3657,14 +3682,14 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
}
// Exposed wrapper for AcceptBlockHeader
-bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, BlockValidationState& state, const CBlockIndex** ppindex)
+bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, bool min_pow_checked, BlockValidationState& state, const CBlockIndex** ppindex)
{
AssertLockNotHeld(cs_main);
{
LOCK(cs_main);
for (const CBlockHeader& header : headers) {
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
- bool accepted{AcceptBlockHeader(header, state, &pindex)};
+ bool accepted{AcceptBlockHeader(header, state, &pindex, min_pow_checked)};
ActiveChainstate().CheckBlockIndex();
if (!accepted) {
@@ -3686,8 +3711,33 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>&
return true;
}
+void ChainstateManager::ReportHeadersPresync(const arith_uint256& work, int64_t height, int64_t timestamp)
+{
+ AssertLockNotHeld(cs_main);
+ const auto& chainstate = ActiveChainstate();
+ {
+ LOCK(cs_main);
+ // Don't report headers presync progress if we already have a post-minchainwork header chain.
+ // This means we lose reporting for potentially legitimate, but unlikely, deep reorgs, but
+ // prevent attackers that spam low-work headers from filling our logs.
+ if (m_best_header->nChainWork >= UintToArith256(GetConsensus().nMinimumChainWork)) return;
+ // Rate limit headers presync updates to 4 per second, as these are not subject to DoS
+ // protection.
+ auto now = std::chrono::steady_clock::now();
+ if (now < m_last_presync_update + std::chrono::milliseconds{250}) return;
+ m_last_presync_update = now;
+ }
+ bool initial_download = chainstate.IsInitialBlockDownload();
+ uiInterface.NotifyHeaderTip(GetSynchronizationState(initial_download), height, timestamp, /*presync=*/true);
+ if (initial_download) {
+ const int64_t blocks_left{(GetTime() - timestamp) / GetConsensus().nPowTargetSpacing};
+ const double progress{100.0 * height / (height + blocks_left)};
+ LogPrintf("Pre-synchronizing blockheaders, height: %d (~%.2f%%)\n", height, progress);
+ }
+}
+
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
-bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock)
+bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked)
{
const CBlock& block = *pblock;
@@ -3697,7 +3747,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
CBlockIndex *pindexDummy = nullptr;
CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
- bool accepted_header{m_chainman.AcceptBlockHeader(block, state, &pindex)};
+ bool accepted_header{m_chainman.AcceptBlockHeader(block, state, &pindex, min_pow_checked)};
CheckBlockIndex();
if (!accepted_header)
@@ -3770,7 +3820,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
return true;
}
-bool ChainstateManager::ProcessNewBlock(const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block)
+bool ChainstateManager::ProcessNewBlock(const std::shared_ptr<const CBlock>& block, bool force_processing, bool min_pow_checked, bool* new_block)
{
AssertLockNotHeld(cs_main);
@@ -3791,7 +3841,7 @@ bool ChainstateManager::ProcessNewBlock(const std::shared_ptr<const CBlock>& blo
bool ret = CheckBlock(*block, state, GetConsensus());
if (ret) {
// Store to disk
- ret = ActiveChainstate().AcceptBlock(block, state, &pindex, force_processing, nullptr, new_block);
+ ret = ActiveChainstate().AcceptBlock(block, state, &pindex, force_processing, nullptr, new_block, min_pow_checked);
}
if (!ret) {
GetMainSignals().BlockChecked(*block, state);
@@ -3812,7 +3862,7 @@ bool ChainstateManager::ProcessNewBlock(const std::shared_ptr<const CBlock>& blo
MempoolAcceptResult ChainstateManager::ProcessTransaction(const CTransactionRef& tx, bool test_accept)
{
AssertLockHeld(cs_main);
- CChainState& active_chainstate = ActiveChainstate();
+ Chainstate& active_chainstate = ActiveChainstate();
if (!active_chainstate.GetMempool()) {
TxValidationState state;
state.Invalid(TxValidationResult::TX_NO_MEMPOOL, "no-mempool");
@@ -3825,10 +3875,10 @@ MempoolAcceptResult ChainstateManager::ProcessTransaction(const CTransactionRef&
bool TestBlockValidity(BlockValidationState& state,
const CChainParams& chainparams,
- CChainState& chainstate,
+ Chainstate& chainstate,
const CBlock& block,
CBlockIndex* pindexPrev,
- const std::function<int64_t()>& adjusted_time_callback,
+ const std::function<NodeClock::time_point()>& adjusted_time_callback,
bool fCheckPOW,
bool fCheckMerkleRoot)
{
@@ -3857,7 +3907,7 @@ bool TestBlockValidity(BlockValidationState& state,
}
/* This function is called from the RPC code for pruneblockchain */
-void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeight)
+void PruneBlockFilesManual(Chainstate& active_chainstate, int nManualPruneHeight)
{
BlockValidationState state;
if (!active_chainstate.FlushStateToDisk(
@@ -3866,16 +3916,14 @@ void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeigh
}
}
-void CChainState::LoadMempool(const ArgsManager& args)
+void Chainstate::LoadMempool(const fs::path& load_path, FopenFn mockable_fopen_function)
{
if (!m_mempool) return;
- if (args.GetBoolArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
- ::LoadMempool(*m_mempool, *this);
- }
- m_mempool->SetIsLoaded(!ShutdownRequested());
+ ::LoadMempool(*m_mempool, load_path, *this, mockable_fopen_function);
+ m_mempool->SetLoadTried(!ShutdownRequested());
}
-bool CChainState::LoadChainTip()
+bool Chainstate::LoadChainTip()
{
AssertLockHeld(cs_main);
const CCoinsViewCache& coins_cache = CoinsTip();
@@ -3891,7 +3939,7 @@ bool CChainState::LoadChainTip()
if (!pindex) {
return false;
}
- m_chain.SetTip(pindex);
+ m_chain.SetTip(*pindex);
PruneBlockIndexCandidates();
tip = m_chain.Tip();
@@ -3914,7 +3962,7 @@ CVerifyDB::~CVerifyDB()
}
bool CVerifyDB::VerifyDB(
- CChainState& chainstate,
+ Chainstate& chainstate,
const Consensus::Params& consensus_params,
CCoinsView& coinsview,
int nCheckLevel, int nCheckDepth)
@@ -4030,7 +4078,7 @@ bool CVerifyDB::VerifyDB(
}
/** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */
-bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs)
+bool Chainstate::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs)
{
AssertLockHeld(cs_main);
// TODO: merge with ConnectBlock
@@ -4051,7 +4099,7 @@ bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& i
return true;
}
-bool CChainState::ReplayBlocks()
+bool Chainstate::ReplayBlocks()
{
LOCK(cs_main);
@@ -4119,7 +4167,7 @@ bool CChainState::ReplayBlocks()
return true;
}
-bool CChainState::NeedsRedownload() const
+bool Chainstate::NeedsRedownload() const
{
AssertLockHeld(cs_main);
@@ -4137,7 +4185,7 @@ bool CChainState::NeedsRedownload() const
return false;
}
-void CChainState::UnloadBlockIndex()
+void Chainstate::UnloadBlockIndex()
{
AssertLockHeld(::cs_main);
nBlockSequenceId = 1;
@@ -4206,7 +4254,7 @@ bool ChainstateManager::LoadBlockIndex()
// detecting "holistically" whether the block index under consideration
// relied on an assumed-valid ancestor, but this proved to be too slow to
// be practical.
- for (CChainState* chainstate : GetAll()) {
+ for (Chainstate* chainstate : GetAll()) {
if (chainstate->reliesOnAssumedValid() ||
pindex->nHeight < first_assumed_valid_height) {
chainstate->setBlockIndexCandidates.insert(pindex);
@@ -4235,7 +4283,7 @@ bool ChainstateManager::LoadBlockIndex()
return true;
}
-bool CChainState::LoadGenesisBlock()
+bool Chainstate::LoadGenesisBlock()
{
LOCK(cs_main);
@@ -4261,12 +4309,17 @@ bool CChainState::LoadGenesisBlock()
return true;
}
-void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
+void Chainstate::LoadExternalBlockFile(
+ FILE* fileIn,
+ FlatFilePos* dbp,
+ std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent)
{
AssertLockNotHeld(m_chainstate_mutex);
- // Map of disk positions for blocks with unknown parent (only used for reindex)
- static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
- int64_t nStart = GetTimeMillis();
+
+ // Either both should be specified (-reindex), or neither (-loadblock).
+ assert(!dbp == !blocks_with_unknown_parent);
+
+ const auto start{SteadyClock::now()};
int nLoaded = 0;
try {
@@ -4315,8 +4368,9 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
if (hash != m_params.GetConsensus().hashGenesisBlock && !m_blockman.LookupBlockIndex(block.hashPrevBlock)) {
LogPrint(BCLog::REINDEX, "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
block.hashPrevBlock.ToString());
- if (dbp)
- mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
+ if (dbp && blocks_with_unknown_parent) {
+ blocks_with_unknown_parent->emplace(block.hashPrevBlock, *dbp);
+ }
continue;
}
@@ -4324,7 +4378,7 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
const CBlockIndex* pindex = m_blockman.LookupBlockIndex(hash);
if (!pindex || (pindex->nStatus & BLOCK_HAVE_DATA) == 0) {
BlockValidationState state;
- if (AcceptBlock(pblock, state, nullptr, true, dbp, nullptr)) {
+ if (AcceptBlock(pblock, state, nullptr, true, dbp, nullptr, true)) {
nLoaded++;
}
if (state.IsError()) {
@@ -4345,13 +4399,15 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
NotifyHeaderTip(*this);
+ if (!blocks_with_unknown_parent) continue;
+
// Recursively process earlier encountered successors of this block
std::deque<uint256> queue;
queue.push_back(hash);
while (!queue.empty()) {
uint256 head = queue.front();
queue.pop_front();
- std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
+ auto range = blocks_with_unknown_parent->equal_range(head);
while (range.first != range.second) {
std::multimap<uint256, FlatFilePos>::iterator it = range.first;
std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
@@ -4360,13 +4416,13 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
head.ToString());
LOCK(cs_main);
BlockValidationState dummy;
- if (AcceptBlock(pblockrecursive, dummy, nullptr, true, &it->second, nullptr)) {
+ if (AcceptBlock(pblockrecursive, dummy, nullptr, true, &it->second, nullptr, true)) {
nLoaded++;
queue.push_back(pblockrecursive->GetHash());
}
}
range.first++;
- mapBlocksUnknownParent.erase(it);
+ blocks_with_unknown_parent->erase(it);
NotifyHeaderTip(*this);
}
}
@@ -4377,10 +4433,10 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
} catch (const std::runtime_error& e) {
AbortNode(std::string("System error: ") + e.what());
}
- LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, GetTimeMillis() - nStart);
+ LogPrintf("Loaded %i blocks from external file in %dms\n", nLoaded, Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
}
-void CChainState::CheckBlockIndex()
+void Chainstate::CheckBlockIndex()
{
if (!fCheckBlockIndex) {
return;
@@ -4602,7 +4658,7 @@ void CChainState::CheckBlockIndex()
assert(nNodes == forward.size());
}
-std::string CChainState::ToString()
+std::string Chainstate::ToString()
{
AssertLockHeld(::cs_main);
CBlockIndex* tip = m_chain.Tip();
@@ -4611,7 +4667,7 @@ std::string CChainState::ToString()
tip ? tip->nHeight : -1, tip ? tip->GetBlockHash().ToString() : "null");
}
-bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
+bool Chainstate::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
{
AssertLockHeld(::cs_main);
if (coinstip_size == m_coinstip_cache_size_bytes &&
@@ -4643,153 +4699,6 @@ bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
return ret;
}
-static const uint64_t MEMPOOL_DUMP_VERSION = 1;
-
-bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mockable_fopen_function)
-{
- int64_t nExpiryTimeout = gArgs.GetIntArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60;
- FILE* filestr{mockable_fopen_function(gArgs.GetDataDirNet() / "mempool.dat", "rb")};
- CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
- if (file.IsNull()) {
- LogPrintf("Failed to open mempool file from disk. Continuing anyway.\n");
- return false;
- }
-
- int64_t count = 0;
- int64_t expired = 0;
- int64_t failed = 0;
- int64_t already_there = 0;
- int64_t unbroadcast = 0;
- int64_t nNow = GetTime();
-
- try {
- uint64_t version;
- file >> version;
- if (version != MEMPOOL_DUMP_VERSION) {
- return false;
- }
- uint64_t num;
- file >> num;
- while (num) {
- --num;
- CTransactionRef tx;
- int64_t nTime;
- int64_t nFeeDelta;
- file >> tx;
- file >> nTime;
- file >> nFeeDelta;
-
- CAmount amountdelta = nFeeDelta;
- if (amountdelta) {
- pool.PrioritiseTransaction(tx->GetHash(), amountdelta);
- }
- if (nTime > nNow - nExpiryTimeout) {
- LOCK(cs_main);
- const auto& accepted = AcceptToMemoryPool(active_chainstate, tx, nTime, /*bypass_limits=*/false, /*test_accept=*/false);
- if (accepted.m_result_type == MempoolAcceptResult::ResultType::VALID) {
- ++count;
- } else {
- // mempool may contain the transaction already, e.g. from
- // wallet(s) having loaded it while we were processing
- // mempool transactions; consider these as valid, instead of
- // failed, but mark them as 'already there'
- if (pool.exists(GenTxid::Txid(tx->GetHash()))) {
- ++already_there;
- } else {
- ++failed;
- }
- }
- } else {
- ++expired;
- }
- if (ShutdownRequested())
- return false;
- }
- std::map<uint256, CAmount> mapDeltas;
- file >> mapDeltas;
-
- for (const auto& i : mapDeltas) {
- pool.PrioritiseTransaction(i.first, i.second);
- }
-
- std::set<uint256> unbroadcast_txids;
- file >> unbroadcast_txids;
- unbroadcast = unbroadcast_txids.size();
- for (const auto& txid : unbroadcast_txids) {
- // Ensure transactions were accepted to mempool then add to
- // unbroadcast set.
- if (pool.get(txid) != nullptr) pool.AddUnbroadcastTx(txid);
- }
- } catch (const std::exception& e) {
- LogPrintf("Failed to deserialize mempool data on disk: %s. Continuing anyway.\n", e.what());
- return false;
- }
-
- LogPrintf("Imported mempool transactions from disk: %i succeeded, %i failed, %i expired, %i already there, %i waiting for initial broadcast\n", count, failed, expired, already_there, unbroadcast);
- return true;
-}
-
-bool DumpMempool(const CTxMemPool& pool, FopenFn mockable_fopen_function, bool skip_file_commit)
-{
- int64_t start = GetTimeMicros();
-
- std::map<uint256, CAmount> mapDeltas;
- std::vector<TxMempoolInfo> vinfo;
- std::set<uint256> unbroadcast_txids;
-
- static Mutex dump_mutex;
- LOCK(dump_mutex);
-
- {
- LOCK(pool.cs);
- for (const auto &i : pool.mapDeltas) {
- mapDeltas[i.first] = i.second;
- }
- vinfo = pool.infoAll();
- unbroadcast_txids = pool.GetUnbroadcastTxs();
- }
-
- int64_t mid = GetTimeMicros();
-
- try {
- FILE* filestr{mockable_fopen_function(gArgs.GetDataDirNet() / "mempool.dat.new", "wb")};
- if (!filestr) {
- return false;
- }
-
- CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
-
- uint64_t version = MEMPOOL_DUMP_VERSION;
- file << version;
-
- file << (uint64_t)vinfo.size();
- for (const auto& i : vinfo) {
- file << *(i.tx);
- file << int64_t{count_seconds(i.m_time)};
- file << int64_t{i.nFeeDelta};
- mapDeltas.erase(i.tx->GetHash());
- }
-
- file << mapDeltas;
-
- LogPrintf("Writing %d unbroadcast transactions to disk.\n", unbroadcast_txids.size());
- file << unbroadcast_txids;
-
- if (!skip_file_commit && !FileCommit(file.Get()))
- throw std::runtime_error("FileCommit failed");
- file.fclose();
- if (!RenameOver(gArgs.GetDataDirNet() / "mempool.dat.new", gArgs.GetDataDirNet() / "mempool.dat")) {
- throw std::runtime_error("Rename failed");
- }
- int64_t last = GetTimeMicros();
- LogPrintf("Dumped mempool: %gs to copy, %gs to dump\n", (mid-start)*MICRO, (last-mid)*MICRO);
- } catch (const std::exception& e) {
- LogPrintf("Failed to dump mempool: %s. Continuing anyway.\n", e.what());
- return false;
- }
- return true;
-}
-
//! Guess how far we are in the verification process at the given block index
//! require cs_main if pindex has not been validated yet (because nChainTx might be unset)
double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pindex) {
@@ -4819,10 +4728,10 @@ std::optional<uint256> ChainstateManager::SnapshotBlockhash() const
return std::nullopt;
}
-std::vector<CChainState*> ChainstateManager::GetAll()
+std::vector<Chainstate*> ChainstateManager::GetAll()
{
LOCK(::cs_main);
- std::vector<CChainState*> out;
+ std::vector<Chainstate*> out;
if (!IsSnapshotValidated() && m_ibd_chainstate) {
out.push_back(m_ibd_chainstate.get());
@@ -4835,18 +4744,18 @@ std::vector<CChainState*> ChainstateManager::GetAll()
return out;
}
-CChainState& ChainstateManager::InitializeChainstate(
+Chainstate& ChainstateManager::InitializeChainstate(
CTxMemPool* mempool, const std::optional<uint256>& snapshot_blockhash)
{
AssertLockHeld(::cs_main);
bool is_snapshot = snapshot_blockhash.has_value();
- std::unique_ptr<CChainState>& to_modify =
+ std::unique_ptr<Chainstate>& to_modify =
is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate;
if (to_modify) {
throw std::logic_error("should not be overwriting a chainstate");
}
- to_modify.reset(new CChainState(mempool, m_blockman, *this, snapshot_blockhash));
+ to_modify.reset(new Chainstate(mempool, m_blockman, *this, snapshot_blockhash));
// Snapshot chainstates and initial IBD chaintates always become active.
if (is_snapshot || (!is_snapshot && !m_active_chainstate)) {
@@ -4872,7 +4781,7 @@ const AssumeutxoData* ExpectedAssumeutxo(
}
bool ChainstateManager::ActivateSnapshot(
- CAutoFile& coins_file,
+ AutoFile& coins_file,
const SnapshotMetadata& metadata,
bool in_memory)
{
@@ -4916,7 +4825,7 @@ bool ChainstateManager::ActivateSnapshot(
}
auto snapshot_chainstate = WITH_LOCK(::cs_main,
- return std::make_unique<CChainState>(
+ return std::make_unique<Chainstate>(
/*mempool=*/nullptr, m_blockman, *this, base_blockhash));
{
@@ -4966,8 +4875,8 @@ static void FlushSnapshotToDisk(CCoinsViewCache& coins_cache, bool snapshot_load
}
bool ChainstateManager::PopulateAndValidateSnapshot(
- CChainState& snapshot_chainstate,
- CAutoFile& coins_file,
+ Chainstate& snapshot_chainstate,
+ AutoFile& coins_file,
const SnapshotMetadata& metadata)
{
// It's okay to release cs_main before we're done using `coins_cache` because we know
@@ -5060,7 +4969,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
// Important that we set this. This and the coins_cache accesses above are
// sort of a layer violation, but either we reach into the innards of
- // CCoinsViewCache here or we have to invert some of the CChainState to
+ // CCoinsViewCache here or we have to invert some of the Chainstate to
// embed them in a snapshot-activation-specific CCoinsViewCache bulk load
// method.
coins_cache.SetBestBlock(base_blockhash);
@@ -5107,7 +5016,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
return false;
}
- snapshot_chainstate.m_chain.SetTip(snapshot_start_block);
+ snapshot_chainstate.m_chain.SetTip(*snapshot_start_block);
// The remainder of this function requires modifying data protected by cs_main.
LOCK(::cs_main);
@@ -5139,7 +5048,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
index->nStatus |= BLOCK_ASSUMED_VALID;
}
- // Fake BLOCK_OPT_WITNESS so that CChainState::NeedsRedownload()
+ // Fake BLOCK_OPT_WITNESS so that Chainstate::NeedsRedownload()
// won't ask to rewind the entire assumed-valid chain on startup.
if (DeploymentActiveAt(*index, *this, Consensus::DEPLOYMENT_SEGWIT)) {
index->nStatus |= BLOCK_OPT_WITNESS;
@@ -5162,7 +5071,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
return true;
}
-CChainState& ChainstateManager::ActiveChainstate() const
+Chainstate& ChainstateManager::ActiveChainstate() const
{
LOCK(::cs_main);
assert(m_active_chainstate);
diff --git a/src/validation.h b/src/validation.h
index 3b6cd509c6..9ba206855f 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -43,7 +43,7 @@
#include <utility>
#include <vector>
-class CChainState;
+class Chainstate;
class CBlockTreeDB;
class CTxMemPool;
class ChainstateManager;
@@ -59,8 +59,6 @@ namespace Consensus {
struct Params;
} // namespace Consensus
-/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
-static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336;
/** Maximum number of dedicated script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 15;
/** -par default (number of script-checking threads, 0 = auto) */
@@ -70,8 +68,6 @@ static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static constexpr bool DEFAULT_COINSTATSINDEX{false};
static const char* const DEFAULT_BLOCKFILTERINDEX = "0";
-/** Default for -persistmempool */
-static const bool DEFAULT_PERSIST_MEMPOOL = true;
/** Default for -stopatheight */
static const int DEFAULT_STOPATHEIGHT = 0;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pruned. */
@@ -104,7 +100,6 @@ extern uint256 g_best_block;
* False indicates all script checking is done on the main threadMessageHandler thread.
*/
extern bool g_parallel_script_checks;
-extern bool fRequireStandard;
extern bool fCheckBlockIndex;
extern bool fCheckpointsEnabled;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
@@ -132,7 +127,7 @@ bool AbortNode(BlockValidationState& state, const std::string& strMessage, const
double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex* pindex);
/** Prune block files up to a given height */
-void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeight);
+void PruneBlockFilesManual(Chainstate& active_chainstate, int nManualPruneHeight);
/**
* Validation result for a single transaction mempool acceptance.
@@ -152,7 +147,7 @@ struct MempoolAcceptResult {
const TxValidationState m_state;
// The following fields are only present when m_result_type = ResultType::VALID or MEMPOOL_ENTRY
- /** Mempool transactions replaced by the tx per BIP 125 rules. */
+ /** Mempool transactions replaced by the tx. */
const std::optional<std::list<CTransactionRef>> m_replaced_transactions;
/** Virtual size as used by the mempool, calculated using serialized size and sigops. */
const std::optional<int64_t> m_vsize;
@@ -245,7 +240,7 @@ struct PackageMempoolAcceptResult
*
* @returns a MempoolAcceptResult indicating whether the transaction was accepted/rejected with reason.
*/
-MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, const CTransactionRef& tx,
+MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,
int64_t accept_time, bool bypass_limits, bool test_accept)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -257,16 +252,16 @@ MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, const CTr
* If a transaction fails, validation will exit early and some results may be missing. It is also
* possible for the package to be partially submitted.
*/
-PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTxMemPool& pool,
+PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,
const Package& txns, bool test_accept)
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
-/* Transaction policy functions */
+/* Mempool validation helper functions */
/**
* Check if transaction will be final in the next block to be created.
*/
-bool CheckFinalTxAtTip(const CBlockIndex* active_chain_tip, const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+bool CheckFinalTxAtTip(const CBlockIndex& active_chain_tip, const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/**
* Check if transaction will be BIP68 final in the next block to be created on top of tip.
@@ -328,7 +323,7 @@ public:
};
/** Initializes the script-execution cache */
-void InitScriptExecutionCache();
+[[nodiscard]] bool InitScriptExecutionCache(size_t max_size_bytes);
/** Functions for validating blocks and updating the block tree */
@@ -338,20 +333,26 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu
/** Check a block is completely valid from start to finish (only works on top of our current best block) */
bool TestBlockValidity(BlockValidationState& state,
const CChainParams& chainparams,
- CChainState& chainstate,
+ Chainstate& chainstate,
const CBlock& block,
CBlockIndex* pindexPrev,
- const std::function<int64_t()>& adjusted_time_callback,
+ const std::function<NodeClock::time_point()>& adjusted_time_callback,
bool fCheckPOW = true,
bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+/** Check with the proof of work on each blockheader matches the value in nBits */
+bool HasValidProofOfWork(const std::vector<CBlockHeader>& headers, const Consensus::Params& consensusParams);
+
+/** Return the sum of the work on a given set of headers */
+arith_uint256 CalculateHeadersWork(const std::vector<CBlockHeader>& headers);
+
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */
class CVerifyDB {
public:
CVerifyDB();
~CVerifyDB();
bool VerifyDB(
- CChainState& chainstate,
+ Chainstate& chainstate,
const Consensus::Params& consensus_params,
CCoinsView& coinsview,
int nCheckLevel,
@@ -367,7 +368,7 @@ enum DisconnectResult
class ConnectTrace;
-/** @see CChainState::FlushStateToDisk */
+/** @see Chainstate::FlushStateToDisk */
enum class FlushStateMode {
NONE,
IF_NEEDED,
@@ -420,7 +421,7 @@ enum class CoinsCacheSizeState
};
/**
- * CChainState stores and provides an API to update our local knowledge of the
+ * Chainstate stores and provides an API to update our local knowledge of the
* current best chain.
*
* Eventually, the API here is targeted at being exposed externally as a
@@ -433,7 +434,7 @@ enum class CoinsCacheSizeState
* whereas block information and metadata independent of the current tip is
* kept in `BlockManager`.
*/
-class CChainState
+class Chainstate
{
protected:
/**
@@ -471,7 +472,7 @@ protected:
public:
//! Reference to a BlockManager instance which itself is shared across all
- //! CChainState instances.
+ //! Chainstate instances.
node::BlockManager& m_blockman;
/** Chain parameters for this chainstate */
@@ -483,7 +484,7 @@ public:
//! chainstate within deeply nested method calls.
ChainstateManager& m_chainman;
- explicit CChainState(
+ explicit Chainstate(
CTxMemPool* mempool,
node::BlockManager& blockman,
ChainstateManager& chainman,
@@ -579,8 +580,36 @@ public:
bool ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
- /** Import blocks from an external file */
- void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr)
+ /**
+ * Import blocks from an external file
+ *
+ * During reindexing, this function is called for each block file (datadir/blocks/blk?????.dat).
+ * It reads all blocks contained in the given file and attempts to process them (add them to the
+ * block index). The blocks may be out of order within each file and across files. Often this
+ * function reads a block but finds that its parent hasn't been read yet, so the block can't be
+ * processed yet. The function will add an entry to the blocks_with_unknown_parent map (which is
+ * passed as an argument), so that when the block's parent is later read and processed, this
+ * function can re-read the child block from disk and process it.
+ *
+ * Because a block's parent may be in a later file, not just later in the same file, the
+ * blocks_with_unknown_parent map must be passed in and out with each call. It's a multimap,
+ * rather than just a map, because multiple blocks may have the same parent (when chain splits
+ * or stale blocks exist). It maps from parent-hash to child-disk-position.
+ *
+ * This function can also be used to read blocks from user-specified block files using the
+ * -loadblock= option. There's no unknown-parent tracking, so the last two arguments are omitted.
+ *
+ *
+ * @param[in] fileIn FILE handle to file containing blocks to read
+ * @param[in] dbp (optional) Disk block position (only for reindex)
+ * @param[in,out] blocks_with_unknown_parent (optional) Map of disk positions for blocks with
+ * unknown parent, key is parent block hash
+ * (only used for reindex)
+ * */
+ void LoadExternalBlockFile(
+ FILE* fileIn,
+ FlatFilePos* dbp = nullptr,
+ std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent = nullptr)
EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex);
/**
@@ -627,7 +656,7 @@ public:
EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex)
LOCKS_EXCLUDED(::cs_main);
- bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Block (dis)connection on a given view:
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view)
@@ -681,7 +710,7 @@ public:
void CheckBlockIndex();
/** Load the persisted mempool from disk */
- void LoadMempool(const ArgsManager& args);
+ void LoadMempool(const fs::path& load_path, fsbridge::FopenFn mockable_fopen_function = fsbridge::fopen);
/** Update the chain tip based on database information, i.e. CoinsTip()'s best block. */
bool LoadChainTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@@ -785,7 +814,7 @@ private:
//! 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.
- std::unique_ptr<CChainState> m_ibd_chainstate GUARDED_BY(::cs_main);
+ std::unique_ptr<Chainstate> m_ibd_chainstate GUARDED_BY(::cs_main);
//! A chainstate initialized on the basis of a UTXO snapshot. If this is
//! non-null, it is always our active chainstate.
@@ -796,7 +825,7 @@ private:
//! 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.
- std::unique_ptr<CChainState> m_snapshot_chainstate GUARDED_BY(::cs_main);
+ std::unique_ptr<Chainstate> m_snapshot_chainstate GUARDED_BY(::cs_main);
//! Points to either the ibd or snapshot chainstate; indicates our
//! most-work chain.
@@ -807,7 +836,7 @@ private:
//! 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.
- CChainState* m_active_chainstate GUARDED_BY(::cs_main) {nullptr};
+ Chainstate* m_active_chainstate GUARDED_BY(::cs_main) {nullptr};
//! If true, the assumed-valid chainstate has been fully validated
//! by the background validation chainstate.
@@ -815,36 +844,54 @@ private:
CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr};
- const CChainParams m_chainparams;
-
- const std::function<int64_t()> m_adjusted_time_callback;
-
//! Internal helper for ActivateSnapshot().
[[nodiscard]] bool PopulateAndValidateSnapshot(
- CChainState& snapshot_chainstate,
- CAutoFile& coins_file,
+ Chainstate& snapshot_chainstate,
+ AutoFile& coins_file,
const node::SnapshotMetadata& metadata);
/**
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
* that it doesn't descend from an invalid block, and then add it to m_block_index.
+ * Caller must set min_pow_checked=true in order to add a new header to the
+ * block index (permanent memory storage), indicating that the header is
+ * known to be part of a sufficiently high-work chain (anti-dos check).
*/
bool AcceptBlockHeader(
const CBlockHeader& block,
BlockValidationState& state,
- CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
- friend CChainState;
+ CBlockIndex** ppindex,
+ bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ friend Chainstate;
+
+ /** Most recent headers presync progress update, for rate-limiting. */
+ std::chrono::time_point<std::chrono::steady_clock> m_last_presync_update GUARDED_BY(::cs_main) {};
public:
- using Options = ChainstateManagerOpts;
+ using Options = kernel::ChainstateManagerOpts;
- explicit ChainstateManager(const Options& opts)
- : m_chainparams{opts.chainparams},
- m_adjusted_time_callback{Assert(opts.adjusted_time_callback)} {};
+ explicit ChainstateManager(Options options) : m_options{std::move(options)}
+ {
+ Assert(m_options.adjusted_time_callback);
+ }
- const CChainParams& GetParams() const { return m_chainparams; }
- const Consensus::Params& GetConsensus() const { return m_chainparams.GetConsensus(); }
+ const CChainParams& GetParams() const { return m_options.chainparams; }
+ const Consensus::Params& GetConsensus() const { return m_options.chainparams.GetConsensus(); }
+
+ /**
+ * Alias for ::cs_main.
+ * Should be used in new code to make it easier to make ::cs_main a member
+ * of this class.
+ * Generally, methods of this class should be annotated to require this
+ * mutex. This will make calling code more verbose, but also help to:
+ * - Clarify that the method will acquire a mutex that heavily affects
+ * overall performance.
+ * - Force call sites to think how long they need to acquire the mutex to
+ * get consistent results.
+ */
+ RecursiveMutex& GetMutex() const LOCK_RETURNED(::cs_main) { return ::cs_main; }
+ const Options m_options;
std::thread m_load_block;
//! A single BlockManager instance is shared across each constructed
//! chainstate to avoid duplicating block metadata.
@@ -889,19 +936,19 @@ public:
// constructor
//! @param[in] snapshot_blockhash If given, signify that this chainstate
//! is based on a snapshot.
- CChainState& InitializeChainstate(
+ Chainstate& InitializeChainstate(
CTxMemPool* mempool,
const std::optional<uint256>& snapshot_blockhash = std::nullopt)
LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
//! Get all chainstates currently being used.
- std::vector<CChainState*> GetAll();
+ std::vector<Chainstate*> GetAll();
//! Construct and activate a Chainstate on the basis of UTXO snapshot data.
//!
//! Steps:
//!
- //! - Initialize an unused CChainState.
+ //! - Initialize an unused Chainstate.
//! - Load its `CoinsViews` contents from `coins_file`.
//! - Verify that the hash of the resulting coinsdb matches the expected hash
//! per assumeutxo chain parameters.
@@ -911,13 +958,13 @@ public:
//! - Move the new chainstate to `m_snapshot_chainstate` and make it our
//! ChainstateActive().
[[nodiscard]] bool ActivateSnapshot(
- CAutoFile& coins_file, const node::SnapshotMetadata& metadata, bool in_memory);
+ AutoFile& coins_file, const node::SnapshotMetadata& metadata, bool in_memory);
//! The most-work chain.
- CChainState& ActiveChainstate() const;
- CChain& ActiveChain() const { return ActiveChainstate().m_chain; }
- int ActiveHeight() const { return ActiveChain().Height(); }
- CBlockIndex* ActiveTip() const { return ActiveChain().Tip(); }
+ Chainstate& ActiveChainstate() const;
+ CChain& ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) { return ActiveChainstate().m_chain; }
+ int ActiveHeight() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) { return ActiveChain().Height(); }
+ CBlockIndex* ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex()) { return ActiveChain().Tip(); }
node::BlockMap& BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
{
@@ -955,10 +1002,15 @@ public:
*
* @param[in] block The block we want to process.
* @param[in] force_processing Process this block even if unrequested; used for non-network block sources.
+ * @param[in] min_pow_checked True if proof-of-work anti-DoS checks have
+ * been done by caller for headers chain
+ * (note: only affects headers acceptance; if
+ * block header is already present in block
+ * index then this parameter has no effect)
* @param[out] new_block A boolean which is set to indicate if the block was first received via this call
* @returns If the block was processed, independently of block validity
*/
- bool ProcessNewBlock(const std::shared_ptr<const CBlock>& block, bool force_processing, bool* new_block) LOCKS_EXCLUDED(cs_main);
+ bool ProcessNewBlock(const std::shared_ptr<const CBlock>& block, bool force_processing, bool min_pow_checked, bool* new_block) LOCKS_EXCLUDED(cs_main);
/**
* Process incoming block headers.
@@ -967,10 +1019,11 @@ public:
* validationinterface callback.
*
* @param[in] block The block headers themselves
+ * @param[in] min_pow_checked True if proof-of-work anti-DoS checks have been done by caller for headers chain
* @param[out] state This may be set to an Error state if any error occurred processing them
* @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
*/
- bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
+ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, bool min_pow_checked, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
/**
* Try to add a transaction to the memory pool.
@@ -994,6 +1047,12 @@ public:
/** Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks). */
std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBlockIndex* pindexPrev) const;
+ /** This is used by net_processing to report pre-synchronization progress of headers, as
+ * headers are not yet fed to validation during that time, but validation is (for now)
+ * responsible for logging and signalling through NotifyHeaderTip, so it needs this
+ * information. */
+ void ReportHeadersPresync(const arith_uint256& work, int64_t height, int64_t timestamp);
+
~ChainstateManager();
};
@@ -1016,14 +1075,6 @@ bool DeploymentEnabled(const ChainstateManager& chainman, DEP dep)
return DeploymentEnabled(chainman.GetConsensus(), dep);
}
-using FopenFn = std::function<FILE*(const fs::path&, const char*)>;
-
-/** Dump the mempool to disk. */
-bool DumpMempool(const CTxMemPool& pool, FopenFn mockable_fopen_function = fsbridge::fopen, bool skip_file_commit = false);
-
-/** Load the mempool from disk. */
-bool LoadMempool(CTxMemPool& pool, CChainState& active_chainstate, FopenFn mockable_fopen_function = fsbridge::fopen);
-
/**
* Return the expected assumeutxo value for a given height, if one exists.
*
diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp
index f8230f7a1d..3a9d277f65 100644
--- a/src/wallet/bdb.cpp
+++ b/src/wallet/bdb.cpp
@@ -3,6 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <compat/compat.h>
#include <fs.h>
#include <wallet/bdb.h>
#include <wallet/db.h>
@@ -315,12 +316,6 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const bool read_only, b
env = database.env.get();
pdb = database.m_db.get();
strFile = fs::PathToString(database.m_filename);
- if (!Exists(std::string("version"))) {
- bool fTmp = fReadOnly;
- fReadOnly = false;
- Write(std::string("version"), CLIENT_VERSION);
- fReadOnly = fTmp;
- }
}
void BerkeleyDatabase::Open()
@@ -437,7 +432,7 @@ void BerkeleyEnvironment::ReloadDbEnv()
});
std::vector<fs::path> filenames;
- for (auto it : m_databases) {
+ for (const auto& it : m_databases) {
filenames.push_back(it.first);
}
// Close the individual Db's
@@ -538,7 +533,7 @@ bool BerkeleyDatabase::Rewrite(const char* pszSkip)
void BerkeleyEnvironment::Flush(bool fShutdown)
{
- int64_t nStart = GetTimeMillis();
+ const auto start{SteadyClock::now()};
// Flush log data to the actual data file on all files that are not in use
LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: [%s] Flush(%s)%s\n", strPath, fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
if (!fDbEnvInit)
@@ -566,7 +561,7 @@ void BerkeleyEnvironment::Flush(bool fShutdown)
no_dbs_accessed = false;
}
}
- LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart);
+ LogPrint(BCLog::WALLETDB, "BerkeleyEnvironment::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
if (fShutdown) {
char** listp;
if (no_dbs_accessed) {
@@ -596,14 +591,14 @@ bool BerkeleyDatabase::PeriodicFlush()
const std::string strFile = fs::PathToString(m_filename);
LogPrint(BCLog::WALLETDB, "Flushing %s\n", strFile);
- int64_t nStart = GetTimeMillis();
+ const auto start{SteadyClock::now()};
// Flush wallet file so it's self contained
env->CloseDb(m_filename);
env->CheckpointLSN(strFile);
m_refcount = -1;
- LogPrint(BCLog::WALLETDB, "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart);
+ LogPrint(BCLog::WALLETDB, "Flushed %s %dms\n", strFile, Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
return true;
}
diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp
index 07df8d9fc8..b568e90998 100644
--- a/src/wallet/coinselection.cpp
+++ b/src/wallet/coinselection.cpp
@@ -104,9 +104,6 @@ std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_poo
if (curr_waste <= best_waste) {
best_selection = curr_selection;
best_waste = curr_waste;
- if (best_waste == 0) {
- break;
- }
}
curr_waste -= (curr_value - selection_target); // Remove the excess value as we will be selecting different coins now
backtrack = true;
@@ -159,7 +156,7 @@ std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_poo
for (const size_t& i : best_selection) {
result.AddInput(utxo_pool.at(i));
}
- result.ComputeAndSetWaste(CAmount{0});
+ result.ComputeAndSetWaste(cost_of_change, cost_of_change, CAmount{0});
assert(best_waste == result.GetWaste());
return result;
@@ -169,6 +166,12 @@ std::optional<SelectionResult> SelectCoinsSRD(const std::vector<OutputGroup>& ut
{
SelectionResult result(target_value, SelectionAlgorithm::SRD);
+ // Include change for SRD as we want to avoid making really small change if the selection just
+ // barely meets the target. Just use the lower bound change target instead of the randomly
+ // generated one, since SRD will result in a random change amount anyway; avoid making the
+ // target needlessly large.
+ target_value += CHANGE_LOWER;
+
std::vector<size_t> indexes;
indexes.resize(utxo_pool.size());
std::iota(indexes.begin(), indexes.end(), 0);
@@ -392,20 +395,26 @@ CAmount GetSelectionWaste(const std::set<COutput>& inputs, CAmount change_cost,
return waste;
}
-CAmount GenerateChangeTarget(CAmount payment_value, FastRandomContext& rng)
+CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_fee, FastRandomContext& rng)
{
if (payment_value <= CHANGE_LOWER / 2) {
- return CHANGE_LOWER;
+ return change_fee + CHANGE_LOWER;
} else {
// random value between 50ksat and min (payment_value * 2, 1milsat)
const auto upper_bound = std::min(payment_value * 2, CHANGE_UPPER);
- return rng.randrange(upper_bound - CHANGE_LOWER) + CHANGE_LOWER;
+ return change_fee + rng.randrange(upper_bound - CHANGE_LOWER) + CHANGE_LOWER;
}
}
-void SelectionResult::ComputeAndSetWaste(CAmount change_cost)
+void SelectionResult::ComputeAndSetWaste(const CAmount min_viable_change, const CAmount change_cost, const CAmount change_fee)
{
- m_waste = GetSelectionWaste(m_selected_inputs, change_cost, m_target, m_use_effective);
+ const CAmount change = GetChange(min_viable_change, change_fee);
+
+ if (change > 0) {
+ m_waste = GetSelectionWaste(m_selected_inputs, change_cost, m_target, m_use_effective);
+ } else {
+ m_waste = GetSelectionWaste(m_selected_inputs, 0, m_target, m_use_effective);
+ }
}
CAmount SelectionResult::GetWaste() const
@@ -418,6 +427,11 @@ CAmount SelectionResult::GetSelectedValue() const
return std::accumulate(m_selected_inputs.cbegin(), m_selected_inputs.cend(), CAmount{0}, [](CAmount sum, const auto& coin) { return sum + coin.txout.nValue; });
}
+CAmount SelectionResult::GetSelectedEffectiveValue() const
+{
+ return std::accumulate(m_selected_inputs.cbegin(), m_selected_inputs.cend(), CAmount{0}, [](CAmount sum, const auto& coin) { return sum + coin.GetEffectiveValue(); });
+}
+
void SelectionResult::Clear()
{
m_selected_inputs.clear();
@@ -430,6 +444,16 @@ void SelectionResult::AddInput(const OutputGroup& group)
m_use_effective = !group.m_subtract_fee_outputs;
}
+void SelectionResult::Merge(const SelectionResult& other)
+{
+ m_target += other.m_target;
+ m_use_effective |= other.m_use_effective;
+ if (m_algo == SelectionAlgorithm::MANUAL) {
+ m_algo = other.m_algo;
+ }
+ util::insert(m_selected_inputs, other.m_selected_inputs);
+}
+
const std::set<COutput>& SelectionResult::GetInputSet() const
{
return m_selected_inputs;
@@ -467,4 +491,24 @@ std::string GetAlgorithmName(const SelectionAlgorithm algo)
}
assert(false);
}
+
+CAmount SelectionResult::GetChange(const CAmount min_viable_change, const CAmount change_fee) const
+{
+ // change = SUM(inputs) - SUM(outputs) - fees
+ // 1) With SFFO we don't pay any fees
+ // 2) Otherwise we pay all the fees:
+ // - input fees are covered by GetSelectedEffectiveValue()
+ // - non_input_fee is included in m_target
+ // - change_fee
+ const CAmount change = m_use_effective
+ ? GetSelectedEffectiveValue() - m_target - change_fee
+ : GetSelectedValue() - m_target;
+
+ if (change < min_viable_change) {
+ return 0;
+ }
+
+ return change;
+}
+
} // namespace wallet
diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h
index 9135e48104..761c2be0b3 100644
--- a/src/wallet/coinselection.h
+++ b/src/wallet/coinselection.h
@@ -123,10 +123,12 @@ struct CoinSelectionParams {
/** Mininmum change to target in Knapsack solver: select coins to cover the payment and
* at least this value of change. */
CAmount m_min_change_target{0};
+ /** Minimum amount for creating a change output.
+ * If change budget is smaller than min_change then we forgo creation of change output.
+ */
+ CAmount min_viable_change{0};
/** Cost of creating the change output. */
CAmount m_change_fee{0};
- /** The pre-determined minimum value to target when funding a change output. */
- CAmount m_change_target{0};
/** Cost of creating the change output + cost of spending the change output in the future. */
CAmount m_cost_of_change{0};
/** The targeted feerate of the transaction being built. */
@@ -254,6 +256,7 @@ struct OutputGroup
/** Choose a random change target for each transaction to make it harder to fingerprint the Core
* wallet based on the change output values of transactions it creates.
+ * Change target covers at least change fees and adds a random value on top of it.
* The random value is between 50ksat and min(2 * payment_value, 1milsat)
* When payment_value <= 25ksat, the value is just 50ksat.
*
@@ -263,8 +266,9 @@ struct OutputGroup
* coins selected are just sufficient to cover the payment amount ("unnecessary input" heuristic).
*
* @param[in] payment_value Average payment value of the transaction output(s).
+ * @param[in] change_fee Fee for creating a change output.
*/
-[[nodiscard]] CAmount GenerateChangeTarget(CAmount payment_value, FastRandomContext& rng);
+[[nodiscard]] CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_fee, FastRandomContext& rng);
enum class SelectionAlgorithm : uint8_t
{
@@ -281,17 +285,16 @@ struct SelectionResult
private:
/** Set of inputs selected by the algorithm to use in the transaction */
std::set<COutput> m_selected_inputs;
+ /** The target the algorithm selected for. Equal to the recipient amount plus non-input fees */
+ CAmount m_target;
+ /** The algorithm used to produce this result */
+ SelectionAlgorithm m_algo;
/** Whether the input values for calculations should be the effective value (true) or normal value (false) */
bool m_use_effective{false};
/** The computed waste */
std::optional<CAmount> m_waste;
public:
- /** The target the algorithm selected for. Note that this may not be equal to the recipient amount as it can include non-input fees */
- const CAmount m_target;
- /** The algorithm used to produce this result */
- const SelectionAlgorithm m_algo;
-
explicit SelectionResult(const CAmount target, SelectionAlgorithm algo)
: m_target(target), m_algo(algo) {}
@@ -300,20 +303,47 @@ public:
/** Get the sum of the input values */
[[nodiscard]] CAmount GetSelectedValue() const;
+ [[nodiscard]] CAmount GetSelectedEffectiveValue() const;
+
void Clear();
void AddInput(const OutputGroup& group);
/** Calculates and stores the waste for this selection via GetSelectionWaste */
- void ComputeAndSetWaste(CAmount change_cost);
+ void ComputeAndSetWaste(const CAmount min_viable_change, const CAmount change_cost, const CAmount change_fee);
[[nodiscard]] CAmount GetWaste() const;
+ void Merge(const SelectionResult& other);
+
/** Get m_selected_inputs */
const std::set<COutput>& GetInputSet() const;
/** Get the vector of COutputs that will be used to fill in a CTransaction's vin */
std::vector<COutput> GetShuffledInputVector() const;
bool operator<(SelectionResult other) const;
+
+ /** Get the amount for the change output after paying needed fees.
+ *
+ * The change amount is not 100% precise due to discrepancies in fee calculation.
+ * The final change amount (if any) should be corrected after calculating the final tx fees.
+ * When there is a discrepancy, most of the time the final change would be slightly bigger than estimated.
+ *
+ * Following are the possible factors of discrepancy:
+ * + non-input fees always include segwit flags
+ * + input fee estimation always include segwit stack size
+ * + input fees are rounded individually and not collectively, which leads to small rounding errors
+ * - input counter size is always assumed to be 1vbyte
+ *
+ * @param[in] min_viable_change Minimum amount for change output, if change would be less then we forgo change
+ * @param[in] change_fee Fees to include change output in the tx
+ * @returns Amount for change output, 0 when there is no change.
+ *
+ */
+ CAmount GetChange(const CAmount min_viable_change, const CAmount change_fee) const;
+
+ CAmount GetTarget() const { return m_target; }
+
+ SelectionAlgorithm GetAlgo() const { return m_algo; }
};
std::optional<SelectionResult> SelectCoinsBnB(std::vector<OutputGroup>& utxo_pool, const CAmount& selection_target, const CAmount& cost_of_change);
diff --git a/src/wallet/dump.cpp b/src/wallet/dump.cpp
index d80c3e25b0..f7fee443d0 100644
--- a/src/wallet/dump.cpp
+++ b/src/wallet/dump.cpp
@@ -41,7 +41,7 @@ bool DumpWallet(const ArgsManager& args, CWallet& wallet, bilingual_str& error)
return false;
}
- CHashWriter hasher(0, 0);
+ HashWriter hasher{};
WalletDatabase& db = wallet.GetDatabase();
std::unique_ptr<DatabaseBatch> batch = db.MakeBatch();
@@ -132,7 +132,7 @@ bool CreateFromDump(const ArgsManager& args, const std::string& name, const fs::
std::ifstream dump_file{dump_path};
// Compute the checksum
- CHashWriter hasher(0, 0);
+ HashWriter hasher{};
uint256 checksum;
// Check the magic and version
diff --git a/src/wallet/external_signer_scriptpubkeyman.cpp b/src/wallet/external_signer_scriptpubkeyman.cpp
index 9d5f58b784..76de51ac3e 100644
--- a/src/wallet/external_signer_scriptpubkeyman.cpp
+++ b/src/wallet/external_signer_scriptpubkeyman.cpp
@@ -45,7 +45,8 @@ ExternalSigner ExternalSignerScriptPubKeyMan::GetExternalSigner() {
std::vector<ExternalSigner> signers;
ExternalSigner::Enumerate(command, signers, Params().NetworkIDString());
if (signers.empty()) throw std::runtime_error(std::string(__func__) + ": No external signers found");
- // TODO: add fingerprint argument in case of multiple signers
+ // TODO: add fingerprint argument instead of failing in case of multiple signers.
+ if (signers.size() > 1) throw std::runtime_error(std::string(__func__) + ": More than one external signer found. Please connect only one at a time.");
return signers[0];
}
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 5e70ed4a30..6d7bb299cc 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <consensus/validation.h>
#include <interfaces/chain.h>
#include <policy/fees.h>
#include <policy/policy.h>
@@ -19,9 +20,9 @@
namespace wallet {
//! Check whether transaction has descendant in wallet or mempool, or has been
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
-static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWalletTx& wtx, std::vector<bilingual_str>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
+static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWalletTx& wtx, bool require_mine, std::vector<bilingual_str>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
- if (wallet.HasWalletSpend(wtx.GetHash())) {
+ if (wallet.HasWalletSpend(wtx.tx)) {
errors.push_back(Untranslated("Transaction has descendants in the wallet"));
return feebumper::Result::INVALID_PARAMETER;
}
@@ -48,20 +49,21 @@ static feebumper::Result PreconditionChecks(const CWallet& wallet, const CWallet
return feebumper::Result::WALLET_ERROR;
}
- // check that original tx consists entirely of our inputs
- // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
- isminefilter filter = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
- if (!AllInputsMine(wallet, *wtx.tx, filter)) {
- errors.push_back(Untranslated("Transaction contains inputs that don't belong to this wallet"));
- return feebumper::Result::WALLET_ERROR;
+ if (require_mine) {
+ // check that original tx consists entirely of our inputs
+ // if not, we can't bump the fee, because the wallet has no way of knowing the value of the other inputs (thus the fee)
+ isminefilter filter = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
+ if (!AllInputsMine(wallet, *wtx.tx, filter)) {
+ errors.push_back(Untranslated("Transaction contains inputs that don't belong to this wallet"));
+ return feebumper::Result::WALLET_ERROR;
+ }
}
-
return feebumper::Result::OK;
}
//! Check if the user provided a valid feeRate
-static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, std::vector<bilingual_str>& errors)
+static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CFeeRate& newFeerate, const int64_t maxTxSize, CAmount old_fee, std::vector<bilingual_str>& errors)
{
// check that fee rate is higher than mempool's minimum fee
// (no point in bumping fee if we know that the new tx won't be accepted to the mempool)
@@ -83,8 +85,6 @@ static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wt
CFeeRate incrementalRelayFee = std::max(wallet.chain().relayIncrementalFee(), CFeeRate(WALLET_INCREMENTAL_RELAY_FEE));
// Given old total fee and transaction size, calculate the old feeRate
- isminefilter filter = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
- CAmount old_fee = CachedTxGetDebit(wallet, wtx, filter) - wtx.tx->GetValueOut();
const int64_t txSize = GetVirtualTransactionSize(*(wtx.tx));
CFeeRate nOldFeeRate(old_fee, txSize);
// Min total fee is old fee + relay fee
@@ -128,8 +128,8 @@ static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, con
// WALLET_INCREMENTAL_RELAY_FEE value to future proof against changes to
// network wide policy for incremental relay fee that our node may not be
// aware of. This ensures we're over the required relay fee rate
- // (BIP 125 rule 4). The replacement tx will be at least as large as the
- // original tx, so the total fee will be greater (BIP 125 rule 3)
+ // (Rule 4). The replacement tx will be at least as large as the
+ // original tx, so the total fee will be greater (Rule 3)
CFeeRate node_incremental_relay_fee = wallet.chain().relayIncrementalFee();
CFeeRate wallet_incremental_relay_fee = CFeeRate(WALLET_INCREMENTAL_RELAY_FEE);
feerate += std::max(node_incremental_relay_fee, wallet_incremental_relay_fee);
@@ -150,12 +150,12 @@ bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid)
if (wtx == nullptr) return false;
std::vector<bilingual_str> errors_dummy;
- feebumper::Result res = PreconditionChecks(wallet, *wtx, errors_dummy);
+ feebumper::Result res = PreconditionChecks(wallet, *wtx, /* require_mine=*/ true, errors_dummy);
return res == feebumper::Result::OK;
}
Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCoinControl& coin_control, std::vector<bilingual_str>& errors,
- CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx)
+ CAmount& old_fee, CAmount& new_fee, CMutableTransaction& mtx, bool require_mine)
{
// We are going to modify coin control later, copy to re-use
CCoinControl new_coin_control(coin_control);
@@ -169,13 +169,63 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
}
const CWalletTx& wtx = it->second;
- Result result = PreconditionChecks(wallet, wtx, errors);
+ // Retrieve all of the UTXOs and add them to coin control
+ // While we're here, calculate the input amount
+ std::map<COutPoint, Coin> coins;
+ CAmount input_value = 0;
+ std::vector<CTxOut> spent_outputs;
+ for (const CTxIn& txin : wtx.tx->vin) {
+ coins[txin.prevout]; // Create empty map entry keyed by prevout.
+ }
+ wallet.chain().findCoins(coins);
+ for (const CTxIn& txin : wtx.tx->vin) {
+ const Coin& coin = coins.at(txin.prevout);
+ if (coin.out.IsNull()) {
+ errors.push_back(Untranslated(strprintf("%s:%u is already spent", txin.prevout.hash.GetHex(), txin.prevout.n)));
+ return Result::MISC_ERROR;
+ }
+ if (wallet.IsMine(txin.prevout)) {
+ new_coin_control.Select(txin.prevout);
+ } else {
+ new_coin_control.SelectExternal(txin.prevout, coin.out);
+ }
+ input_value += coin.out.nValue;
+ spent_outputs.push_back(coin.out);
+ }
+
+ // Figure out if we need to compute the input weight, and do so if necessary
+ PrecomputedTransactionData txdata;
+ txdata.Init(*wtx.tx, std::move(spent_outputs), /* force=*/ true);
+ for (unsigned int i = 0; i < wtx.tx->vin.size(); ++i) {
+ const CTxIn& txin = wtx.tx->vin.at(i);
+ const Coin& coin = coins.at(txin.prevout);
+
+ if (new_coin_control.IsExternalSelected(txin.prevout)) {
+ // For external inputs, we estimate the size using the size of this input
+ int64_t input_weight = GetTransactionInputWeight(txin);
+ // Because signatures can have different sizes, we need to figure out all of the
+ // signature sizes and replace them with the max sized signature.
+ // In order to do this, we verify the script with a special SignatureChecker which
+ // will observe the signatures verified and record their sizes.
+ SignatureWeights weights;
+ TransactionSignatureChecker tx_checker(wtx.tx.get(), i, coin.out.nValue, txdata, MissingDataBehavior::FAIL);
+ SignatureWeightChecker size_checker(weights, tx_checker);
+ VerifyScript(txin.scriptSig, coin.out.scriptPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, size_checker);
+ // Add the difference between max and current to input_weight so that it represents the largest the input could be
+ input_weight += weights.GetWeightDiffToMax();
+ new_coin_control.SetInputWeight(txin.prevout, input_weight);
+ }
+ }
+
+ Result result = PreconditionChecks(wallet, wtx, require_mine, errors);
if (result != Result::OK) {
return result;
}
// Fill in recipients(and preserve a single change key if there is one)
+ // While we're here, calculate the output amount
std::vector<CRecipient> recipients;
+ CAmount output_value = 0;
for (const auto& output : wtx.tx->vout) {
if (!OutputIsChange(wallet, output)) {
CRecipient recipient = {output.scriptPubKey, output.nValue, false};
@@ -185,16 +235,22 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
ExtractDestination(output.scriptPubKey, change_dest);
new_coin_control.destChange = change_dest;
}
+ output_value += output.nValue;
}
- isminefilter filter = wallet.GetLegacyScriptPubKeyMan() && wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) ? ISMINE_WATCH_ONLY : ISMINE_SPENDABLE;
- old_fee = CachedTxGetDebit(wallet, wtx, filter) - wtx.tx->GetValueOut();
+ old_fee = input_value - output_value;
if (coin_control.m_feerate) {
// The user provided a feeRate argument.
// We calculate this here to avoid compiler warning on the cs_wallet lock
- const int64_t maxTxSize{CalculateMaximumSignedTxSize(*wtx.tx, &wallet).vsize};
- Result res = CheckFeeRate(wallet, wtx, *new_coin_control.m_feerate, maxTxSize, errors);
+ // We need to make a temporary transaction with no input witnesses as the dummy signer expects them to be empty for external inputs
+ CMutableTransaction mtx{*wtx.tx};
+ for (auto& txin : mtx.vin) {
+ txin.scriptSig.clear();
+ txin.scriptWitness.SetNull();
+ }
+ const int64_t maxTxSize{CalculateMaximumSignedTxSize(CTransaction(mtx), &wallet, &new_coin_control).vsize};
+ Result res = CheckFeeRate(wallet, wtx, *new_coin_control.m_feerate, maxTxSize, old_fee, errors);
if (res != Result::OK) {
return res;
}
@@ -219,19 +275,18 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
new_coin_control.m_min_depth = 1;
constexpr int RANDOM_CHANGE_POSITION = -1;
- bilingual_str fail_reason;
- FeeCalculation fee_calc_out;
- std::optional<CreatedTransactionResult> txr = CreateTransaction(wallet, recipients, RANDOM_CHANGE_POSITION, fail_reason, new_coin_control, fee_calc_out, false);
- if (!txr) {
- errors.push_back(Untranslated("Unable to create transaction.") + Untranslated(" ") + fail_reason);
+ auto res = CreateTransaction(wallet, recipients, RANDOM_CHANGE_POSITION, new_coin_control, false);
+ if (!res) {
+ errors.push_back(Untranslated("Unable to create transaction.") + Untranslated(" ") + util::ErrorString(res));
return Result::WALLET_ERROR;
}
+ const auto& txr = *res;
// Write back new fee if successful
- new_fee = txr->fee;
+ new_fee = txr.fee;
// Write back transaction
- mtx = CMutableTransaction(*txr->tx);
+ mtx = CMutableTransaction(*txr.tx);
return Result::OK;
}
@@ -255,7 +310,7 @@ Result CommitTransaction(CWallet& wallet, const uint256& txid, CMutableTransacti
const CWalletTx& oldWtx = it->second;
// make sure the transaction still has no descendants and hasn't been mined in the meantime
- Result result = PreconditionChecks(wallet, oldWtx, errors);
+ Result result = PreconditionChecks(wallet, oldWtx, /* require_mine=*/ false, errors);
if (result != Result::OK) {
return result;
}
diff --git a/src/wallet/feebumper.h b/src/wallet/feebumper.h
index 191878a137..760ab58e5c 100644
--- a/src/wallet/feebumper.h
+++ b/src/wallet/feebumper.h
@@ -5,6 +5,8 @@
#ifndef BITCOIN_WALLET_FEEBUMPER_H
#define BITCOIN_WALLET_FEEBUMPER_H
+#include <consensus/consensus.h>
+#include <script/interpreter.h>
#include <primitives/transaction.h>
class uint256;
@@ -31,14 +33,25 @@ enum class Result
//! Return whether transaction can be bumped.
bool TransactionCanBeBumped(const CWallet& wallet, const uint256& txid);
-//! Create bumpfee transaction based on feerate estimates.
+/** Create bumpfee transaction based on feerate estimates.
+ *
+ * @param[in] wallet The wallet to use for this bumping
+ * @param[in] txid The txid of the transaction to bump
+ * @param[in] coin_control A CCoinControl object which provides feerates and other information used for coin selection
+ * @param[out] errors Errors
+ * @param[out] old_fee The fee the original transaction pays
+ * @param[out] new_fee the fee that the bump transaction pays
+ * @param[out] mtx The bump transaction itself
+ * @param[in] require_mine Whether the original transaction must consist of inputs that can be spent by the wallet
+ */
Result CreateRateBumpTransaction(CWallet& wallet,
const uint256& txid,
const CCoinControl& coin_control,
std::vector<bilingual_str>& errors,
CAmount& old_fee,
CAmount& new_fee,
- CMutableTransaction& mtx);
+ CMutableTransaction& mtx,
+ bool require_mine);
//! Sign the new transaction,
//! @return false if the tx couldn't be found or if it was
@@ -55,6 +68,55 @@ Result CommitTransaction(CWallet& wallet,
std::vector<bilingual_str>& errors,
uint256& bumped_txid);
+struct SignatureWeights
+{
+private:
+ int m_sigs_count{0};
+ int64_t m_sigs_weight{0};
+
+public:
+ void AddSigWeight(const size_t weight, const SigVersion sigversion)
+ {
+ switch (sigversion) {
+ case SigVersion::BASE:
+ m_sigs_weight += weight * WITNESS_SCALE_FACTOR;
+ m_sigs_count += 1 * WITNESS_SCALE_FACTOR;
+ break;
+ case SigVersion::WITNESS_V0:
+ m_sigs_weight += weight;
+ m_sigs_count++;
+ break;
+ case SigVersion::TAPROOT:
+ case SigVersion::TAPSCRIPT:
+ assert(false);
+ }
+ }
+
+ int64_t GetWeightDiffToMax() const
+ {
+ // Note: the witness scaling factor is already accounted for because the count is multiplied by it.
+ return (/* max signature size=*/ 72 * m_sigs_count) - m_sigs_weight;
+ }
+};
+
+class SignatureWeightChecker : public DeferringSignatureChecker
+{
+private:
+ SignatureWeights& m_weights;
+
+public:
+ SignatureWeightChecker(SignatureWeights& weights, const BaseSignatureChecker& checker) : DeferringSignatureChecker(checker), m_weights(weights) {}
+
+ bool CheckECDSASignature(const std::vector<unsigned char>& sig, const std::vector<unsigned char>& pubkey, const CScript& script, SigVersion sigversion) const override
+ {
+ if (m_checker.CheckECDSASignature(sig, pubkey, script, sigversion)) {
+ m_weights.AddSigWeight(sig.size(), sigversion);
+ return true;
+ }
+ return false;
+ }
+};
+
} // namespace feebumper
} // namespace wallet
diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp
index 6f81fa30a1..3514d018b7 100644
--- a/src/wallet/fees.cpp
+++ b/src/wallet/fees.cpp
@@ -87,7 +87,7 @@ CFeeRate GetDiscardRate(const CWallet& wallet)
CFeeRate discard_rate = wallet.chain().estimateSmartFee(highest_target, false /* conservative */);
// Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate
discard_rate = (discard_rate == CFeeRate(0)) ? wallet.m_discard_rate : std::min(discard_rate, wallet.m_discard_rate);
- // Discard rate must be at least dustRelayFee
+ // Discard rate must be at least dust relay feerate
discard_rate = std::max(discard_rate, wallet.chain().relayDustFee());
return discard_rate;
}
diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp
index f54b2c83d2..9cf2b677e6 100644
--- a/src/wallet/interfaces.cpp
+++ b/src/wallet/interfaces.cpp
@@ -48,6 +48,8 @@ using interfaces::WalletTxStatus;
using interfaces::WalletValueMap;
namespace wallet {
+// All members of the classes in this namespace are intentionally public, as the
+// classes themselves are private.
namespace {
//! Construct wallet tx struct.
WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
@@ -146,11 +148,10 @@ public:
void abortRescan() override { m_wallet->AbortRescan(); }
bool backupWallet(const std::string& filename) override { return m_wallet->BackupWallet(filename); }
std::string getWalletName() override { return m_wallet->GetName(); }
- bool getNewDestination(const OutputType type, const std::string label, CTxDestination& dest) override
+ util::Result<CTxDestination> getNewDestination(const OutputType type, const std::string& label) override
{
LOCK(m_wallet->cs_wallet);
- bilingual_str error;
- return m_wallet->GetNewDestination(type, label, dest, error);
+ return m_wallet->GetNewDestination(type, label);
}
bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) override
{
@@ -191,29 +192,27 @@ public:
std::string* purpose) override
{
LOCK(m_wallet->cs_wallet);
- auto it = m_wallet->m_address_book.find(dest);
- if (it == m_wallet->m_address_book.end() || it->second.IsChange()) {
- return false;
- }
+ const auto& entry = m_wallet->FindAddressBookEntry(dest, /*allow_change=*/false);
+ if (!entry) return false; // addr not found
if (name) {
- *name = it->second.GetLabel();
+ *name = entry->GetLabel();
}
if (is_mine) {
*is_mine = m_wallet->IsMine(dest);
}
if (purpose) {
- *purpose = it->second.purpose;
+ *purpose = entry->purpose;
}
return true;
}
- std::vector<WalletAddress> getAddresses() override
+ std::vector<WalletAddress> getAddresses() const override
{
LOCK(m_wallet->cs_wallet);
std::vector<WalletAddress> result;
- for (const auto& item : m_wallet->m_address_book) {
- if (item.second.IsChange()) continue;
- result.emplace_back(item.first, m_wallet->IsMine(item.first), item.second.GetLabel(), item.second.purpose);
- }
+ m_wallet->ForEachAddrBookEntry([&](const CTxDestination& dest, const std::string& label, const std::string& purpose, bool is_change) EXCLUSIVE_LOCKS_REQUIRED(m_wallet->cs_wallet) {
+ if (is_change) return;
+ result.emplace_back(dest, m_wallet->IsMine(dest), label, purpose);
+ });
return result;
}
std::vector<std::string> getAddressReceiveRequests() override {
@@ -252,22 +251,21 @@ public:
LOCK(m_wallet->cs_wallet);
return m_wallet->ListLockedCoins(outputs);
}
- CTransactionRef createTransaction(const std::vector<CRecipient>& recipients,
+ util::Result<CTransactionRef> createTransaction(const std::vector<CRecipient>& recipients,
const CCoinControl& coin_control,
bool sign,
int& change_pos,
- CAmount& fee,
- bilingual_str& fail_reason) override
+ CAmount& fee) override
{
LOCK(m_wallet->cs_wallet);
- FeeCalculation fee_calc_out;
- std::optional<CreatedTransactionResult> txr = CreateTransaction(*m_wallet, recipients, change_pos,
- fail_reason, coin_control, fee_calc_out, sign);
- if (!txr) return {};
- fee = txr->fee;
- change_pos = txr->change_pos;
+ auto res = CreateTransaction(*m_wallet, recipients, change_pos,
+ coin_control, sign);
+ if (!res) return util::Error{util::ErrorString(res)};
+ const auto& txr = *res;
+ fee = txr.fee;
+ change_pos = txr.change_pos;
- return txr->tx;
+ return txr.tx;
}
void commitTransaction(CTransactionRef tx,
WalletValueMap value_map,
@@ -293,7 +291,7 @@ public:
CAmount& new_fee,
CMutableTransaction& mtx) override
{
- return feebumper::CreateRateBumpTransaction(*m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx) == feebumper::Result::OK;
+ return feebumper::CreateRateBumpTransaction(*m_wallet.get(), txid, coin_control, errors, old_fee, new_fee, mtx, /* require_mine= */ true) == feebumper::Result::OK;
}
bool signBumpTransaction(CMutableTransaction& mtx) override { return feebumper::SignTransaction(*m_wallet.get(), mtx); }
bool commitBumpTransaction(const uint256& txid,
@@ -322,13 +320,12 @@ public:
}
return {};
}
- std::vector<WalletTx> getWalletTxs() override
+ std::set<WalletTx> getWalletTxs() override
{
LOCK(m_wallet->cs_wallet);
- std::vector<WalletTx> result;
- result.reserve(m_wallet->mapWallet.size());
+ std::set<WalletTx> result;
for (const auto& entry : m_wallet->mapWallet) {
- result.emplace_back(MakeWalletTx(*m_wallet, entry.second));
+ result.emplace(MakeWalletTx(*m_wallet, entry.second));
}
return result;
}
@@ -554,30 +551,46 @@ public:
void setMockTime(int64_t time) override { return SetMockTime(time); }
//! WalletLoader methods
- std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings) override
+ util::Result<std::unique_ptr<Wallet>> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, std::vector<bilingual_str>& warnings) override
{
- std::shared_ptr<CWallet> wallet;
DatabaseOptions options;
DatabaseStatus status;
ReadDatabaseArgs(*m_context.args, options);
options.require_create = true;
options.create_flags = wallet_creation_flags;
options.create_passphrase = passphrase;
- return MakeWallet(m_context, CreateWallet(m_context, name, true /* load_on_start */, options, status, error, warnings));
+ bilingual_str error;
+ std::unique_ptr<Wallet> wallet{MakeWallet(m_context, CreateWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))};
+ if (wallet) {
+ return {std::move(wallet)};
+ } else {
+ return util::Error{error};
+ }
}
- std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
+ util::Result<std::unique_ptr<Wallet>> loadWallet(const std::string& name, std::vector<bilingual_str>& warnings) override
{
DatabaseOptions options;
DatabaseStatus status;
ReadDatabaseArgs(*m_context.args, options);
options.require_existing = true;
- return MakeWallet(m_context, LoadWallet(m_context, name, true /* load_on_start */, options, status, error, warnings));
+ bilingual_str error;
+ std::unique_ptr<Wallet> wallet{MakeWallet(m_context, LoadWallet(m_context, name, /*load_on_start=*/true, options, status, error, warnings))};
+ if (wallet) {
+ return {std::move(wallet)};
+ } else {
+ return util::Error{error};
+ }
}
- std::unique_ptr<Wallet> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
+ util::Result<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) override
{
DatabaseStatus status;
-
- return MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings));
+ bilingual_str error;
+ std::unique_ptr<Wallet> wallet{MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /*load_on_start=*/true, status, error, warnings))};
+ if (wallet) {
+ return {std::move(wallet)};
+ } else {
+ return util::Error{error};
+ }
}
std::string getWalletDir() override
{
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
index c06513588b..6eb0ef5e7a 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -151,7 +151,7 @@ void StartWallets(WalletContext& context, CScheduler& scheduler)
if (context.args->GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) {
scheduler.scheduleEvery([&context] { MaybeCompactWalletDB(context); }, std::chrono::milliseconds{500});
}
- scheduler.scheduleEvery([&context] { MaybeResendWalletTxs(context); }, std::chrono::milliseconds{1000});
+ scheduler.scheduleEvery([&context] { MaybeResendWalletTxs(context); }, 1min);
}
void FlushWallets(WalletContext& context)
diff --git a/src/wallet/receive.cpp b/src/wallet/receive.cpp
index 8de4017371..7fbf2ff8cf 100644
--- a/src/wallet/receive.cpp
+++ b/src/wallet/receive.cpp
@@ -9,15 +9,12 @@
#include <wallet/wallet.h>
namespace wallet {
-isminetype InputIsMine(const CWallet& wallet, const CTxIn &txin)
+isminetype InputIsMine(const CWallet& wallet, const CTxIn& txin)
{
AssertLockHeld(wallet.cs_wallet);
- std::map<uint256, CWalletTx>::const_iterator mi = wallet.mapWallet.find(txin.prevout.hash);
- if (mi != wallet.mapWallet.end())
- {
- const CWalletTx& prev = (*mi).second;
- if (txin.prevout.n < prev.tx->vout.size())
- return wallet.IsMine(prev.tx->vout[txin.prevout.n]);
+ const CWalletTx* prev = wallet.GetWalletTx(txin.prevout.hash);
+ if (prev && txin.prevout.n < prev->tx->vout.size()) {
+ return wallet.IsMine(prev->tx->vout[txin.prevout.n]);
}
return ISMINE_NO;
}
@@ -25,20 +22,8 @@ isminetype InputIsMine(const CWallet& wallet, const CTxIn &txin)
bool AllInputsMine(const CWallet& wallet, const CTransaction& tx, const isminefilter& filter)
{
LOCK(wallet.cs_wallet);
-
- for (const CTxIn& txin : tx.vin)
- {
- auto mi = wallet.mapWallet.find(txin.prevout.hash);
- if (mi == wallet.mapWallet.end())
- return false; // any unknown inputs can't be from us
-
- const CWalletTx& prev = (*mi).second;
-
- if (txin.prevout.n >= prev.tx->vout.size())
- return false; // invalid input!
-
- if (!(wallet.IsMine(prev.tx->vout[txin.prevout.n]) & filter))
- return false;
+ for (const CTxIn& txin : tx.vin) {
+ if (!(InputIsMine(wallet, txin) & filter)) return false;
}
return true;
}
@@ -111,10 +96,10 @@ CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx)
return nChange;
}
-static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CWalletTx::AmountType type, const isminefilter& filter, bool recalculate = false)
+static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CWalletTx::AmountType type, const isminefilter& filter)
{
auto& amount = wtx.m_amounts[type];
- if (recalculate || !amount.m_cached[filter]) {
+ if (!amount.m_cached[filter]) {
amount.Set(filter, type == CWalletTx::DEBIT ? wallet.GetDebit(*wtx.tx, filter) : TxGetCredit(wallet, *wtx.tx, filter));
wtx.m_is_cache_empty = false;
}
@@ -130,12 +115,10 @@ CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const ism
return 0;
CAmount credit = 0;
- if (filter & ISMINE_SPENDABLE) {
+ const isminefilter get_amount_filter{filter & ISMINE_ALL};
+ if (get_amount_filter) {
// GetBalance can assume transactions in mapWallet won't change
- credit += GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, ISMINE_SPENDABLE);
- }
- if (filter & ISMINE_WATCH_ONLY) {
- credit += GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, ISMINE_WATCH_ONLY);
+ credit += GetCachableAmount(wallet, wtx, CWalletTx::CREDIT, get_amount_filter);
}
return credit;
}
@@ -146,11 +129,9 @@ CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, const ismi
return 0;
CAmount debit = 0;
- if (filter & ISMINE_SPENDABLE) {
- debit += GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, ISMINE_SPENDABLE);
- }
- if (filter & ISMINE_WATCH_ONLY) {
- debit += GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, ISMINE_WATCH_ONLY);
+ const isminefilter get_amount_filter{filter & ISMINE_ALL};
+ if (get_amount_filter) {
+ debit += GetCachableAmount(wallet, wtx, CWalletTx::DEBIT, get_amount_filter);
}
return debit;
}
@@ -164,29 +145,18 @@ CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx)
return wtx.nChangeCached;
}
-CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache)
-{
- AssertLockHeld(wallet.cs_wallet);
-
- if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) {
- return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache);
- }
-
- return 0;
-}
-
-CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet& wallet, const CWalletTx& wtx, const bool fUseCache)
+CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
{
AssertLockHeld(wallet.cs_wallet);
if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) {
- return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache);
+ return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, filter);
}
return 0;
}
-CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache, const isminefilter& filter)
+CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
{
AssertLockHeld(wallet.cs_wallet);
@@ -197,7 +167,7 @@ CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx,
if (wallet.IsTxImmatureCoinBase(wtx))
return 0;
- if (fUseCache && allow_cache && wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_cached[filter]) {
+ if (allow_cache && wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_cached[filter]) {
return wtx.m_amounts[CWalletTx::AVAILABLE_CREDIT].m_value[filter];
}
@@ -223,7 +193,8 @@ CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx,
void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
std::list<COutputEntry>& listReceived,
- std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter)
+ std::list<COutputEntry>& listSent, CAmount& nFee, const isminefilter& filter,
+ bool include_change)
{
nFee = 0;
listReceived.clear();
@@ -248,8 +219,7 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
// 2) the output is to us (received)
if (nDebit > 0)
{
- // Don't report 'change' txouts
- if (OutputIsChange(wallet, txout))
+ if (!include_change && OutputIsChange(wallet, txout))
continue;
}
else if (!(fIsMine & filter))
@@ -332,8 +302,8 @@ Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
const CWalletTx& wtx = entry.second;
const bool is_trusted{CachedTxIsTrusted(wallet, wtx, trusted_parents)};
const int tx_depth{wallet.GetTxDepthInMainChain(wtx)};
- const CAmount tx_credit_mine{CachedTxGetAvailableCredit(wallet, wtx, /*fUseCache=*/true, ISMINE_SPENDABLE | reuse_filter)};
- const CAmount tx_credit_watchonly{CachedTxGetAvailableCredit(wallet, wtx, /*fUseCache=*/true, ISMINE_WATCH_ONLY | reuse_filter)};
+ const CAmount tx_credit_mine{CachedTxGetAvailableCredit(wallet, wtx, ISMINE_SPENDABLE | reuse_filter)};
+ const CAmount tx_credit_watchonly{CachedTxGetAvailableCredit(wallet, wtx, ISMINE_WATCH_ONLY | reuse_filter)};
if (is_trusted && tx_depth >= min_depth) {
ret.m_mine_trusted += tx_credit_mine;
ret.m_watchonly_trusted += tx_credit_watchonly;
@@ -342,8 +312,8 @@ Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
ret.m_mine_untrusted_pending += tx_credit_mine;
ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
}
- ret.m_mine_immature += CachedTxGetImmatureCredit(wallet, wtx);
- ret.m_watchonly_immature += CachedTxGetImmatureWatchOnlyCredit(wallet, wtx);
+ ret.m_mine_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_SPENDABLE);
+ ret.m_watchonly_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_WATCH_ONLY);
}
}
return ret;
@@ -446,7 +416,7 @@ std::set< std::set<CTxDestination> > GetAddressGroupings(const CWallet& wallet)
std::set< std::set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
std::map< CTxDestination, std::set<CTxDestination>* > setmap; // map addresses to the unique group containing it
- for (std::set<CTxDestination> _grouping : groupings)
+ for (const std::set<CTxDestination>& _grouping : groupings)
{
// make a set of all the groups hit by this new group
std::set< std::set<CTxDestination>* > hits;
diff --git a/src/wallet/receive.h b/src/wallet/receive.h
index 1caef293f2..9125b1e9aa 100644
--- a/src/wallet/receive.h
+++ b/src/wallet/receive.h
@@ -29,11 +29,9 @@ CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const ism
//! filter decides which addresses will count towards the debit
CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter);
CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx);
-CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache = true)
+CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter)
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
-CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet& wallet, const CWalletTx& wtx, const bool fUseCache = true)
- EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
-CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache = true, const isminefilter& filter = ISMINE_SPENDABLE)
+CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter = ISMINE_SPENDABLE)
EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
struct COutputEntry
{
@@ -44,7 +42,8 @@ struct COutputEntry
void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
std::list<COutputEntry>& listReceived,
std::list<COutputEntry>& listSent,
- CAmount& nFee, const isminefilter& filter);
+ CAmount& nFee, const isminefilter& filter,
+ bool include_change);
bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter);
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx);
diff --git a/src/wallet/rpc/addresses.cpp b/src/wallet/rpc/addresses.cpp
index f25ad59528..903a569cb9 100644
--- a/src/wallet/rpc/addresses.cpp
+++ b/src/wallet/rpc/addresses.cpp
@@ -34,7 +34,7 @@ RPCHelpMan getnewaddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -58,13 +58,12 @@ RPCHelpMan getnewaddress()
output_type = parsed.value();
}
- CTxDestination dest;
- bilingual_str error;
- if (!pwallet->GetNewDestination(output_type, label, dest, error)) {
- throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
+ auto op_dest = pwallet->GetNewDestination(output_type, label);
+ if (!op_dest) {
+ throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, util::ErrorString(op_dest).original);
}
- return EncodeDestination(dest);
+ return EncodeDestination(*op_dest);
},
};
}
@@ -87,7 +86,7 @@ RPCHelpMan getrawchangeaddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -106,12 +105,11 @@ RPCHelpMan getrawchangeaddress()
output_type = parsed.value();
}
- CTxDestination dest;
- bilingual_str error;
- if (!pwallet->GetNewChangeDestination(output_type, dest, error)) {
- throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
+ auto op_dest = pwallet->GetNewChangeDestination(output_type);
+ if (!op_dest) {
+ throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, util::ErrorString(op_dest).original);
}
- return EncodeDestination(dest);
+ return EncodeDestination(*op_dest);
},
};
}
@@ -133,7 +131,7 @@ RPCHelpMan setlabel()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -150,7 +148,7 @@ RPCHelpMan setlabel()
pwallet->SetAddressBook(dest, label, "send");
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -183,7 +181,7 @@ RPCHelpMan listaddressgroupings()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -254,7 +252,7 @@ RPCHelpMan addmultisigaddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet);
@@ -329,7 +327,7 @@ RPCHelpMan keypoolrefill()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
if (pwallet->IsLegacy() && pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
@@ -352,7 +350,7 @@ RPCHelpMan keypoolrefill()
throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -376,14 +374,14 @@ RPCHelpMan newkeypool()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
spk_man.NewKeyPool();
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -550,7 +548,7 @@ RPCHelpMan getaddressinfo()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -580,7 +578,7 @@ RPCHelpMan getaddressinfo()
if (provider) {
auto inferred = InferDescriptor(scriptPubKey, *provider);
- bool solvable = inferred->IsSolvable() || IsSolvable(*provider, scriptPubKey);
+ bool solvable = inferred->IsSolvable();
ret.pushKV("solvable", solvable);
if (solvable) {
ret.pushKV("desc", inferred->ToString());
@@ -637,17 +635,6 @@ RPCHelpMan getaddressinfo()
};
}
-/** Convert CAddressBookData to JSON record. */
-static UniValue AddressBookDataToJSON(const CAddressBookData& data, const bool verbose)
-{
- UniValue ret(UniValue::VOBJ);
- if (verbose) {
- ret.pushKV("name", data.GetLabel());
- }
- ret.pushKV("purpose", data.purpose);
- return ret;
-}
-
RPCHelpMan getaddressesbylabel()
{
return RPCHelpMan{"getaddressesbylabel",
@@ -671,7 +658,7 @@ RPCHelpMan getaddressesbylabel()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -680,10 +667,10 @@ RPCHelpMan getaddressesbylabel()
// Find all addresses that have the given label
UniValue ret(UniValue::VOBJ);
std::set<std::string> addresses;
- for (const std::pair<const CTxDestination, CAddressBookData>& item : pwallet->m_address_book) {
- if (item.second.IsChange()) continue;
- if (item.second.GetLabel() == label) {
- std::string address = EncodeDestination(item.first);
+ pwallet->ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label, const std::string& _purpose, bool _is_change) {
+ if (_is_change) return;
+ if (_label == label) {
+ std::string address = EncodeDestination(_dest);
// CWallet::m_address_book is not expected to contain duplicate
// address strings, but build a separate set as a precaution just in
// case it does.
@@ -693,9 +680,11 @@ RPCHelpMan getaddressesbylabel()
// and since duplicate addresses are unexpected (checked with
// std::set in O(log(N))), UniValue::__pushKV is used instead,
// which currently is O(1).
- ret.__pushKV(address, AddressBookDataToJSON(item.second, false));
+ UniValue value(UniValue::VOBJ);
+ value.pushKV("purpose", _purpose);
+ ret.__pushKV(address, value);
}
- }
+ });
if (ret.empty()) {
throw JSONRPCError(RPC_WALLET_INVALID_LABEL_NAME, std::string("No addresses with label " + label));
@@ -732,7 +721,7 @@ RPCHelpMan listlabels()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -742,13 +731,7 @@ RPCHelpMan listlabels()
}
// Add to a set to sort by label name, then insert into Univalue array
- std::set<std::string> label_set;
- for (const std::pair<const CTxDestination, CAddressBookData>& entry : pwallet->m_address_book) {
- if (entry.second.IsChange()) continue;
- if (purpose.empty() || entry.second.purpose == purpose) {
- label_set.insert(entry.second.GetLabel());
- }
- }
+ std::set<std::string> label_set = pwallet->ListAddrBookLabels(purpose);
UniValue ret(UniValue::VARR);
for (const std::string& name : label_set) {
@@ -780,7 +763,7 @@ RPCHelpMan walletdisplayaddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- if (!wallet) return NullUniValue;
+ if (!wallet) return UniValue::VNULL;
CWallet* const pwallet = wallet.get();
LOCK(pwallet->cs_wallet);
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
index 5f1673fb12..a971331a70 100644
--- a/src/wallet/rpc/backup.cpp
+++ b/src/wallet/rpc/backup.cpp
@@ -100,11 +100,13 @@ RPCHelpMan importprivkey()
"Hint: use importmulti to import more than one private key.\n"
"\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
+ "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
+ "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
"Note: Use \"getwalletinfo\" to query the scanning progress.\n",
{
{"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key (see dumpprivkey)"},
{"label", RPCArg::Type::STR, RPCArg::DefaultHint{"current label if address exists, otherwise \"\""}, "An optional label"},
- {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Rescan the wallet for transactions"},
+ {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Scan the chain and mempool for wallet transactions."},
},
RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
@@ -122,7 +124,7 @@ RPCHelpMan importprivkey()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
@@ -138,7 +140,7 @@ RPCHelpMan importprivkey()
EnsureWalletIsUnlocked(*pwallet);
std::string strSecret = request.params[0].get_str();
- std::string strLabel = "";
+ std::string strLabel;
if (!request.params[1].isNull())
strLabel = request.params[1].get_str();
@@ -190,7 +192,7 @@ RPCHelpMan importprivkey()
RescanWallet(*pwallet, reserver);
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -201,6 +203,8 @@ RPCHelpMan importaddress()
"\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
"\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported address exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
+ "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
+ "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
"If you have the full public key, you should call importpubkey instead of this.\n"
"Hint: use importmulti to import more than one address.\n"
"\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n"
@@ -210,7 +214,7 @@ RPCHelpMan importaddress()
{
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The Bitcoin address (or hex-encoded script)"},
{"label", RPCArg::Type::STR, RPCArg::Default{""}, "An optional label"},
- {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Rescan the wallet for transactions"},
+ {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Scan the chain and mempool for wallet transactions."},
{"p2sh", RPCArg::Type::BOOL, RPCArg::Default{false}, "Add the P2SH version of the script as well"},
},
RPCResult{RPCResult::Type::NONE, "", ""},
@@ -225,7 +229,7 @@ RPCHelpMan importaddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
EnsureLegacyScriptPubKeyMan(*pwallet, true);
@@ -289,13 +293,10 @@ RPCHelpMan importaddress()
if (fRescan)
{
RescanWallet(*pwallet, reserver);
- {
- LOCK(pwallet->cs_wallet);
- pwallet->ReacceptWalletTransactions();
- }
+ pwallet->ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -313,7 +314,7 @@ RPCHelpMan importprunedfunds()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
CMutableTransaction tx;
if (!DecodeHexTx(tx, request.params[0].get_str())) {
@@ -348,7 +349,7 @@ RPCHelpMan importprunedfunds()
CTransactionRef tx_ref = MakeTransactionRef(tx);
if (pwallet->IsMine(*tx_ref)) {
pwallet->AddToWallet(std::move(tx_ref), TxStateConfirmed{merkleBlock.header.GetHash(), height, static_cast<int>(txnIndex)});
- return NullUniValue;
+ return UniValue::VNULL;
}
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction");
@@ -372,7 +373,7 @@ RPCHelpMan removeprunedfunds()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -389,7 +390,7 @@ RPCHelpMan removeprunedfunds()
throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction does not exist in wallet.");
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -401,11 +402,13 @@ RPCHelpMan importpubkey()
"Hint: use importmulti to import more than one public key.\n"
"\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n"
+ "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
+ "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
"Note: Use \"getwalletinfo\" to query the scanning progress.\n",
{
{"pubkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The hex-encoded public key"},
{"label", RPCArg::Type::STR, RPCArg::Default{""}, "An optional label"},
- {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Rescan the wallet for transactions"},
+ {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Scan the chain and mempool for wallet transactions."},
},
RPCResult{RPCResult::Type::NONE, "", ""},
RPCExamples{
@@ -419,7 +422,7 @@ RPCHelpMan importpubkey()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
EnsureLegacyScriptPubKeyMan(*pwallet, true);
@@ -468,13 +471,10 @@ RPCHelpMan importpubkey()
if (fRescan)
{
RescanWallet(*pwallet, reserver);
- {
- LOCK(pwallet->cs_wallet);
- pwallet->ReacceptWalletTransactions();
- }
+ pwallet->ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -484,7 +484,7 @@ RPCHelpMan importwallet()
{
return RPCHelpMan{"importwallet",
"\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n"
- "Note: Use \"getwalletinfo\" to query the scanning progress.\n",
+ "Note: Blockchain and Mempool will be rescanned after a successful import. Use \"getwalletinfo\" to query the scanning progress.\n",
{
{"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet file"},
},
@@ -500,7 +500,7 @@ RPCHelpMan importwallet()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
EnsureLegacyScriptPubKeyMan(*pwallet, true);
@@ -631,7 +631,7 @@ RPCHelpMan importwallet()
if (!fGood)
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys/scripts to wallet");
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -655,7 +655,7 @@ RPCHelpMan dumpprivkey()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
const LegacyScriptPubKeyMan& spk_man = EnsureConstLegacyScriptPubKeyMan(*pwallet);
@@ -705,7 +705,7 @@ RPCHelpMan dumpwallet()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
const CWallet& wallet = *pwallet;
const LegacyScriptPubKeyMan& spk_man = EnsureConstLegacyScriptPubKeyMan(wallet);
@@ -1250,6 +1250,8 @@ RPCHelpMan importmulti()
"Conversely, if all the private keys are provided and the address/script is spendable, the watchonly option must be set to false, or a warning will be returned.\n"
"\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
"may report that the imported keys, addresses or scripts exist but related transactions are still missing.\n"
+ "The rescan parameter can be set to false if the key was never used to create transactions. If it is set to false,\n"
+ "but the key was used to create transactions, rescanblockchain needs to be called with the appropriate block range.\n"
"Note: Use \"getwalletinfo\" to query the scanning progress.\n",
{
{"requests", RPCArg::Type::ARR, RPCArg::Optional::NO, "Data to be imported",
@@ -1291,7 +1293,7 @@ RPCHelpMan importmulti()
"\"requests\""},
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
{
- {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Stating if should rescan the blockchain after all imports"},
+ {"rescan", RPCArg::Type::BOOL, RPCArg::Default{true}, "Scan the chain and mempool for wallet transactions after all imports."},
},
"\"options\""},
},
@@ -1320,7 +1322,7 @@ RPCHelpMan importmulti()
[&](const RPCHelpMan& self, const JSONRPCRequest& mainRequest) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(mainRequest);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
CWallet& wallet{*pwallet};
// Make sure the results are valid at least up to the most recent block
@@ -1387,10 +1389,7 @@ RPCHelpMan importmulti()
}
if (fRescan && fRunScan && requests.size()) {
int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */);
- {
- LOCK(pwallet->cs_wallet);
- pwallet->ReacceptWalletTransactions();
- }
+ pwallet->ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
if (pwallet->IsAbortingRescan()) {
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
@@ -1593,7 +1592,7 @@ RPCHelpMan importdescriptors()
" Use the string \"now\" to substitute the current synced blockchain time.\n"
" \"now\" can be specified to bypass scanning, for outputs which are known to never have been used, and\n"
" 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest timestamp\n"
- " of all descriptors being imported will be scanned.",
+ "of all descriptors being imported will be scanned as well as the mempool.",
/*oneline_description=*/"", {"timestamp | \"now\"", "integer / string"}
},
{"internal", RPCArg::Type::BOOL, RPCArg::Default{false}, "Whether matching outputs should be treated as not incoming payments (e.g. change)"},
@@ -1628,7 +1627,7 @@ RPCHelpMan importdescriptors()
[&](const RPCHelpMan& self, const JSONRPCRequest& main_request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(main_request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
CWallet& wallet{*pwallet};
// Make sure the results are valid at least up to the most recent block
@@ -1681,10 +1680,7 @@ RPCHelpMan importdescriptors()
// Rescan the blockchain using the lowest timestamp
if (rescan) {
int64_t scanned_time = pwallet->RescanFromTime(lowest_timestamp, reserver, true /* update */);
- {
- LOCK(pwallet->cs_wallet);
- pwallet->ReacceptWalletTransactions();
- }
+ pwallet->ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
if (pwallet->IsAbortingRescan()) {
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
@@ -1763,7 +1759,7 @@ RPCHelpMan listdescriptors()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> wallet = GetWalletForJSONRPCRequest(request);
- if (!wallet) return NullUniValue;
+ if (!wallet) return UniValue::VNULL;
if (!wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "listdescriptors is not available for non-descriptor wallets");
@@ -1776,34 +1772,59 @@ RPCHelpMan listdescriptors()
LOCK(wallet->cs_wallet);
- UniValue descriptors(UniValue::VARR);
const auto active_spk_mans = wallet->GetActiveScriptPubKeyMans();
+
+ struct WalletDescInfo {
+ std::string descriptor;
+ uint64_t creation_time;
+ bool active;
+ std::optional<bool> internal;
+ std::optional<std::pair<int64_t,int64_t>> range;
+ int64_t next_index;
+ };
+
+ std::vector<WalletDescInfo> wallet_descriptors;
for (const auto& spk_man : wallet->GetAllScriptPubKeyMans()) {
const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
if (!desc_spk_man) {
throw JSONRPCError(RPC_WALLET_ERROR, "Unexpected ScriptPubKey manager type.");
}
- UniValue spk(UniValue::VOBJ);
LOCK(desc_spk_man->cs_desc_man);
const auto& wallet_descriptor = desc_spk_man->GetWalletDescriptor();
std::string descriptor;
-
if (!desc_spk_man->GetDescriptorString(descriptor, priv)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Can't get descriptor string.");
}
- spk.pushKV("desc", descriptor);
- spk.pushKV("timestamp", wallet_descriptor.creation_time);
- spk.pushKV("active", active_spk_mans.count(desc_spk_man) != 0);
- const auto internal = wallet->IsInternalScriptPubKeyMan(desc_spk_man);
- if (internal.has_value()) {
- spk.pushKV("internal", *internal);
+ const bool is_range = wallet_descriptor.descriptor->IsRange();
+ wallet_descriptors.push_back({
+ descriptor,
+ wallet_descriptor.creation_time,
+ active_spk_mans.count(desc_spk_man) != 0,
+ wallet->IsInternalScriptPubKeyMan(desc_spk_man),
+ is_range ? std::optional(std::make_pair(wallet_descriptor.range_start, wallet_descriptor.range_end)) : std::nullopt,
+ wallet_descriptor.next_index
+ });
+ }
+
+ std::sort(wallet_descriptors.begin(), wallet_descriptors.end(), [](const auto& a, const auto& b) {
+ return a.descriptor < b.descriptor;
+ });
+
+ UniValue descriptors(UniValue::VARR);
+ for (const WalletDescInfo& info : wallet_descriptors) {
+ UniValue spk(UniValue::VOBJ);
+ spk.pushKV("desc", info.descriptor);
+ spk.pushKV("timestamp", info.creation_time);
+ spk.pushKV("active", info.active);
+ if (info.internal.has_value()) {
+ spk.pushKV("internal", info.internal.value());
}
- if (wallet_descriptor.descriptor->IsRange()) {
+ if (info.range.has_value()) {
UniValue range(UniValue::VARR);
- range.push_back(wallet_descriptor.range_start);
- range.push_back(wallet_descriptor.range_end - 1);
+ range.push_back(info.range->first);
+ range.push_back(info.range->second - 1);
spk.pushKV("range", range);
- spk.pushKV("next", wallet_descriptor.next_index);
+ spk.pushKV("next", info.next_index);
}
descriptors.push_back(spk);
}
@@ -1832,7 +1853,7 @@ RPCHelpMan backupwallet()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -1845,7 +1866,7 @@ RPCHelpMan backupwallet()
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
diff --git a/src/wallet/rpc/coins.cpp b/src/wallet/rpc/coins.cpp
index ad59cc94ff..50766f20eb 100644
--- a/src/wallet/rpc/coins.cpp
+++ b/src/wallet/rpc/coins.cpp
@@ -18,10 +18,10 @@
namespace wallet {
static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
- std::set<CTxDestination> addresses;
+ std::vector<CTxDestination> addresses;
if (by_label) {
// Get the set of addresses assigned to label
- addresses = wallet.GetLabelAddresses(LabelFromValue(params[0]));
+ addresses = wallet.ListAddrBookAddresses(CWallet::AddrBookFilter{LabelFromValue(params[0])});
if (addresses.empty()) throw JSONRPCError(RPC_WALLET_ERROR, "Label not found in wallet");
} else {
// Get the address
@@ -29,7 +29,7 @@ static CAmount GetReceived(const CWallet& wallet, const UniValue& params, bool b
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
}
- addresses.insert(dest);
+ addresses.emplace_back(dest);
}
// Filter by own scripts only
@@ -103,7 +103,7 @@ RPCHelpMan getreceivedbyaddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -144,7 +144,7 @@ RPCHelpMan getreceivedbylabel()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -184,7 +184,7 @@ RPCHelpMan getbalance()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -223,7 +223,7 @@ RPCHelpMan getunconfirmedbalance()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -282,7 +282,7 @@ RPCHelpMan lockunspent()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -407,7 +407,7 @@ RPCHelpMan listlockunspent()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -459,7 +459,7 @@ RPCHelpMan getbalances()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
- if (!rpc_wallet) return NullUniValue;
+ if (!rpc_wallet) return UniValue::VNULL;
const CWallet& wallet = *rpc_wallet;
// Make sure the results are valid at least up to the most recent block
@@ -543,6 +543,9 @@ RPCHelpMan listunspent()
{RPCResult::Type::BOOL, "solvable", "Whether we know how to spend this output, ignoring the lack of keys"},
{RPCResult::Type::BOOL, "reused", /*optional=*/true, "(only present if avoid_reuse is set) Whether this output is reused/dirty (sent to an address that was previously spent from)"},
{RPCResult::Type::STR, "desc", /*optional=*/true, "(only when solvable) A descriptor for spending this output"},
+ {RPCResult::Type::ARR, "parent_descs", /*optional=*/false, "List of parent descriptors for the scriptPubKey of this coin.", {
+ {RPCResult::Type::STR, "desc", "The descriptor string."},
+ }},
{RPCResult::Type::BOOL, "safe", "Whether this output is considered safe to spend. Unconfirmed transactions\n"
"from outside keys and unconfirmed replacement transactions are considered unsafe\n"
"and are not eligible for spending by fundrawtransaction and sendtoaddress."},
@@ -559,7 +562,7 @@ RPCHelpMan listunspent()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
int nMinDepth = 1;
if (!request.params[0].isNull()) {
@@ -638,7 +641,7 @@ RPCHelpMan listunspent()
cctl.m_max_depth = nMaxDepth;
cctl.m_include_unsafe_inputs = include_unsafe;
LOCK(pwallet->cs_wallet);
- vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount).coins;
+ vecOutputs = AvailableCoinsListUnspent(*pwallet, &cctl, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount).All();
}
LOCK(pwallet->cs_wallet);
@@ -722,6 +725,7 @@ RPCHelpMan listunspent()
entry.pushKV("desc", descriptor->ToString());
}
}
+ PushParentDescriptors(*pwallet, scriptPubKey, entry);
if (avoid_reuse) entry.pushKV("reused", reused);
entry.pushKV("safe", out.safe);
results.push_back(entry);
diff --git a/src/wallet/rpc/encrypt.cpp b/src/wallet/rpc/encrypt.cpp
index 931c64ca06..a68f52a718 100644
--- a/src/wallet/rpc/encrypt.cpp
+++ b/src/wallet/rpc/encrypt.cpp
@@ -32,7 +32,7 @@ RPCHelpMan walletpassphrase()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
- if (!wallet) return NullUniValue;
+ if (!wallet) return UniValue::VNULL;
CWallet* const pwallet = wallet.get();
int64_t nSleepTime;
@@ -98,7 +98,7 @@ RPCHelpMan walletpassphrase()
}
}, nSleepTime);
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -120,7 +120,7 @@ RPCHelpMan walletpassphrasechange()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -146,7 +146,7 @@ RPCHelpMan walletpassphrasechange()
throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -173,7 +173,7 @@ RPCHelpMan walletlock()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -184,7 +184,7 @@ RPCHelpMan walletlock()
pwallet->Lock();
pwallet->nRelockTime = 0;
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -217,7 +217,7 @@ RPCHelpMan encryptwallet()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
diff --git a/src/wallet/rpc/signmessage.cpp b/src/wallet/rpc/signmessage.cpp
index 438d290030..ae4bd4fbc5 100644
--- a/src/wallet/rpc/signmessage.cpp
+++ b/src/wallet/rpc/signmessage.cpp
@@ -36,7 +36,7 @@ RPCHelpMan signmessage()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp
index 0e8cee5db8..7064a50937 100644
--- a/src/wallet/rpc/spend.cpp
+++ b/src/wallet/rpc/spend.cpp
@@ -156,18 +156,16 @@ UniValue SendMoney(CWallet& wallet, const CCoinControl &coin_control, std::vecto
// Send
constexpr int RANDOM_CHANGE_POSITION = -1;
- bilingual_str error;
- FeeCalculation fee_calc_out;
- std::optional<CreatedTransactionResult> txr = CreateTransaction(wallet, recipients, RANDOM_CHANGE_POSITION, error, coin_control, fee_calc_out, true);
- if (!txr) {
- throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, error.original);
+ auto res = CreateTransaction(wallet, recipients, RANDOM_CHANGE_POSITION, coin_control, true);
+ if (!res) {
+ throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, util::ErrorString(res).original);
}
- CTransactionRef tx = txr->tx;
+ const CTransactionRef& tx = res->tx;
wallet.CommitTransaction(tx, std::move(map_value), {} /* orderForm */);
if (verbose) {
UniValue entry(UniValue::VOBJ);
entry.pushKV("txid", tx->GetHash().GetHex());
- entry.pushKV("fee_reason", StringForFeeReason(fee_calc_out.reason));
+ entry.pushKV("fee_reason", StringForFeeReason(res->fee_calc.reason));
return entry;
}
return tx->GetHash().GetHex();
@@ -226,10 +224,10 @@ RPCHelpMan sendtoaddress()
"transaction, just kept in your wallet."},
{"subtractfeefromamount", RPCArg::Type::BOOL, RPCArg::Default{false}, "The fee will be deducted from the amount being sent.\n"
"The recipient will receive less bitcoins than you enter in the amount field."},
- {"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
+ {"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Signal that this transaction can be replaced by a transaction (BIP 125)"},
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
- {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
- " \"" + FeeModes("\"\n\"") + "\""},
+ {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
+ "\"" + FeeModes("\"\n\"") + "\""},
{"avoid_reuse", RPCArg::Type::BOOL, RPCArg::Default{true}, "(only available if avoid_reuse wallet flag is set) Avoid spending from dirty addresses; addresses are considered\n"
"dirty if they have previously been used in a transaction. If true, this also activates avoidpartialspends, grouping outputs by their addresses."},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
@@ -263,7 +261,7 @@ RPCHelpMan sendtoaddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -335,10 +333,10 @@ RPCHelpMan sendmany()
{"address", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Subtract fee from this address"},
},
},
- {"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
+ {"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Signal that this transaction can be replaced by a transaction (BIP 125)"},
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
- {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
- " \"" + FeeModes("\"\n\"") + "\""},
+ {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
+ "\"" + FeeModes("\"\n\"") + "\""},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{"verbose", RPCArg::Type::BOOL, RPCArg::Default{false}, "If true, return extra infomration about the transaction."},
},
@@ -369,7 +367,7 @@ RPCHelpMan sendmany()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -424,7 +422,7 @@ RPCHelpMan settxfee()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LOCK(pwallet->cs_wallet);
@@ -453,8 +451,8 @@ static std::vector<RPCArg> FundTxDoc(bool solving_data = true)
{
std::vector<RPCArg> args = {
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
- {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
- " \"" + FeeModes("\"\n\"") + "\""},
+ {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
+ "\"" + FeeModes("\"\n\"") + "\""},
{
"replaceable", RPCArg::Type::BOOL, RPCArg::DefaultHint{"wallet default"}, "Marks this transaction as BIP125-replaceable.\n"
"Allows this transaction to be replaced by a transaction with higher fees"
@@ -646,7 +644,7 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to parse descriptor '%s': %s", desc_str, error));
}
desc->Expand(0, desc_out, scripts_temp, desc_out);
- coinControl.m_external_provider = Merge(coinControl.m_external_provider, desc_out);
+ coinControl.m_external_provider.Merge(std::move(desc_out));
}
}
}
@@ -749,7 +747,7 @@ RPCHelpMan fundrawtransaction()
"If that happens, you will need to fund the transaction with different inputs and republish it."},
{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
- {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
"e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
@@ -807,7 +805,7 @@ RPCHelpMan fundrawtransaction()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType(), UniValue::VBOOL});
@@ -897,7 +895,7 @@ RPCHelpMan signrawtransactionwithwallet()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true);
@@ -969,7 +967,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
"still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
"are replaceable).\n"},
{"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
- "\"" + FeeModes("\"\n\"") + "\""},
+ "\"" + FeeModes("\"\n\"") + "\""},
},
"options"},
},
@@ -994,7 +992,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
[want_psbt](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !want_psbt) {
throw JSONRPCError(RPC_WALLET_ERROR, "bumpfee is not available with wallets that have private keys disabled. Use psbtbumpfee instead.");
@@ -1047,7 +1045,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
CMutableTransaction mtx;
feebumper::Result res;
// Targeting feerate bump.
- res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx);
+ res = feebumper::CreateRateBumpTransaction(*pwallet, hash, coin_control, errors, old_fee, new_fee, mtx, /*require_mine=*/ !want_psbt);
if (res != feebumper::Result::OK) {
switch(res) {
case feebumper::Result::INVALID_ADDRESS_OR_KEY:
@@ -1133,20 +1131,20 @@ RPCHelpMan send()
},
},
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
- {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
- " \"" + FeeModes("\"\n\"") + "\""},
+ {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
+ "\"" + FeeModes("\"\n\"") + "\""},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
Cat<std::vector<RPCArg>>(
{
- {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{false}, "If inputs are specified, automatically include more if they are not enough."},
+ {"add_inputs", RPCArg::Type::BOOL, RPCArg::DefaultHint{"false when \"inputs\" are specified, true otherwise"},"Automatically include coins from the wallet to cover the target amount.\n"},
{"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"
"Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"
"If that happens, you will need to fund the transaction with different inputs and republish it."},
{"add_to_wallet", RPCArg::Type::BOOL, RPCArg::Default{true}, "When false, returns a serialized transaction which will not be added to the wallet or broadcast"},
{"change_address", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"change_position", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
- {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\" and \"bech32m\"."},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only.\n"
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
@@ -1211,7 +1209,7 @@ RPCHelpMan send()
);
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]};
InterpretFeeEstimationInstructions(/*conf_target=*/request.params[1], /*estimate_mode=*/request.params[2], /*fee_rate=*/request.params[3], options);
@@ -1254,8 +1252,8 @@ RPCHelpMan sendall()
},
},
{"conf_target", RPCArg::Type::NUM, RPCArg::DefaultHint{"wallet -txconfirmtarget"}, "Confirmation target in blocks"},
- {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
- " \"" + FeeModes("\"\n\"") + "\""},
+ {"estimate_mode", RPCArg::Type::STR, RPCArg::Default{"unset"}, "The fee estimate mode, must be one of (case insensitive):\n"
+ "\"" + FeeModes("\"\n\"") + "\""},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{
"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
@@ -1266,11 +1264,15 @@ RPCHelpMan sendall()
{"include_watching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch-only.\n"
"Only solvable inputs can be used. Watch-only destinations are solvable if the public key and/or output script was imported,\n"
"e.g. with 'importpubkey' or 'importmulti' with the 'pubkeys' or 'desc' field."},
- {"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Use exactly the specified inputs to build the transaction. Specifying inputs is incompatible with send_max. A JSON array of JSON objects",
+ {"inputs", RPCArg::Type::ARR, RPCArg::Default{UniValue::VARR}, "Use exactly the specified inputs to build the transaction. Specifying inputs is incompatible with send_max.",
{
- {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
- {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
- {"sequence", RPCArg::Type::NUM, RPCArg::Optional::NO, "The sequence number"},
+ {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "",
+ {
+ {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"},
+ {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"},
+ {"sequence", RPCArg::Type::NUM, RPCArg::DefaultHint{"depends on the value of the 'replaceable' and 'locktime' arguments"}, "The sequence number"},
+ },
+ },
},
},
{"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
@@ -1316,7 +1318,7 @@ RPCHelpMan sendall()
);
std::shared_ptr<CWallet> const pwallet{GetWalletForJSONRPCRequest(request)};
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
pwallet->BlockUntilSyncedToCurrentChain();
@@ -1378,13 +1380,13 @@ RPCHelpMan sendall()
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not available. UTXO (%s:%d) was already spent.", input.prevout.hash.ToString(), input.prevout.n));
}
const CWalletTx* tx{pwallet->GetWalletTx(input.prevout.hash)};
- if (!tx || pwallet->IsMine(tx->tx->vout[input.prevout.n]) != (coin_control.fAllowWatchOnly ? ISMINE_ALL : ISMINE_SPENDABLE)) {
+ if (!tx || input.prevout.n >= tx->tx->vout.size() || !(pwallet->IsMine(tx->tx->vout[input.prevout.n]) & (coin_control.fAllowWatchOnly ? ISMINE_ALL : ISMINE_SPENDABLE))) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input not found. UTXO (%s:%d) is not part of wallet.", input.prevout.hash.ToString(), input.prevout.n));
}
total_input_value += tx->tx->vout[input.prevout.n].nValue;
}
} else {
- for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, /*nMinimumAmount=*/0).coins) {
+ for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, /*nMinimumAmount=*/0).All()) {
CHECK_NONFATAL(output.input_bytes > 0);
if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) {
continue;
@@ -1400,6 +1402,10 @@ RPCHelpMan sendall()
const CAmount fee_from_size{fee_rate.GetFee(tx_size.vsize)};
const CAmount effective_value{total_input_value - fee_from_size};
+ if (fee_from_size > pwallet->m_default_max_tx_fee) {
+ throw JSONRPCError(RPC_WALLET_ERROR, TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED).original);
+ }
+
if (effective_value <= 0) {
if (send_max) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Total value of UTXO pool too low to pay for transaction, try using lower feerate.");
@@ -1408,8 +1414,13 @@ RPCHelpMan sendall()
}
}
+ // If this transaction is too large, e.g. because the wallet has many UTXOs, it will be rejected by the node's mempool.
+ if (tx_size.weight > MAX_STANDARD_TX_WEIGHT) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Transaction too large.");
+ }
+
CAmount output_amounts_claimed{0};
- for (CTxOut out : rawTx.vout) {
+ for (const CTxOut& out : rawTx.vout) {
output_amounts_claimed += out.nValue;
}
@@ -1492,7 +1503,7 @@ RPCHelpMan walletprocesspsbt()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
const CWallet& wallet{*pwallet};
// Make sure the results are valid at least up to the most recent block
@@ -1580,13 +1591,13 @@ RPCHelpMan walletcreatefundedpsbt()
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
Cat<std::vector<RPCArg>>(
{
- {"add_inputs", RPCArg::Type::BOOL, RPCArg::Default{false}, "If inputs are specified, automatically include more if they are not enough."},
+ {"add_inputs", RPCArg::Type::BOOL, RPCArg::DefaultHint{"false when \"inputs\" are specified, true otherwise"}, "Automatically include coins from the wallet to cover the target amount.\n"},
{"include_unsafe", RPCArg::Type::BOOL, RPCArg::Default{false}, "Include inputs that are not safe to spend (unconfirmed transactions from outside keys and unconfirmed replacement transactions).\n"
"Warning: the resulting transaction may become invalid if one of the unsafe inputs disappears.\n"
"If that happens, you will need to fund the transaction with different inputs and republish it."},
{"changeAddress", RPCArg::Type::STR, RPCArg::DefaultHint{"automatic"}, "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, RPCArg::DefaultHint{"random"}, "The index of the change output"},
- {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
+ {"change_type", RPCArg::Type::STR, RPCArg::DefaultHint{"set by -changetype"}, "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", \"bech32\", and \"bech32m\"."},
{"includeWatching", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Also select inputs which are watch only"},
{"lockUnspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
{"fee_rate", RPCArg::Type::AMOUNT, RPCArg::DefaultHint{"not set, fall back to wallet fee estimation"}, "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
@@ -1619,7 +1630,7 @@ RPCHelpMan walletcreatefundedpsbt()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
CWallet& wallet{*pwallet};
// Make sure the results are valid at least up to the most recent block
@@ -1635,7 +1646,7 @@ RPCHelpMan walletcreatefundedpsbt()
}, true
);
- UniValue options = request.params[3];
+ UniValue options{request.params[3].isNull() ? UniValue::VOBJ : request.params[3]};
CAmount fee;
int change_position;
diff --git a/src/wallet/rpc/transactions.cpp b/src/wallet/rpc/transactions.cpp
index fae9bf3ea5..6b9ec8ce10 100644
--- a/src/wallet/rpc/transactions.cpp
+++ b/src/wallet/rpc/transactions.cpp
@@ -85,14 +85,12 @@ static UniValue ListReceived(const CWallet& wallet, const UniValue& params, cons
filter |= ISMINE_WATCH_ONLY;
}
- bool has_filtered_address = false;
- CTxDestination filtered_address = CNoDestination();
+ std::optional<CTxDestination> filtered_address{std::nullopt};
if (!by_label && !params[3].isNull() && !params[3].get_str().empty()) {
if (!IsValidDestinationString(params[3].get_str())) {
throw JSONRPCError(RPC_WALLET_ERROR, "address_filter parameter was invalid");
}
filtered_address = DecodeDestination(params[3].get_str());
- has_filtered_address = true;
}
// Tally
@@ -106,23 +104,21 @@ static UniValue ListReceived(const CWallet& wallet, const UniValue& params, cons
// Coinbase with less than 1 confirmation is no longer in the main chain
if ((wtx.IsCoinBase() && (nDepth < 1))
- || (wallet.IsTxImmatureCoinBase(wtx) && !include_immature_coinbase))
- {
+ || (wallet.IsTxImmatureCoinBase(wtx) && !include_immature_coinbase)) {
continue;
}
- for (const CTxOut& txout : wtx.tx->vout)
- {
+ for (const CTxOut& txout : wtx.tx->vout) {
CTxDestination address;
if (!ExtractDestination(txout.scriptPubKey, address))
continue;
- if (has_filtered_address && !(filtered_address == address)) {
+ if (filtered_address && !(filtered_address == address)) {
continue;
}
isminefilter mine = wallet.IsMine(address);
- if(!(mine & filter))
+ if (!(mine & filter))
continue;
tallyitem& item = mapTally[address];
@@ -138,70 +134,55 @@ static UniValue ListReceived(const CWallet& wallet, const UniValue& params, cons
UniValue ret(UniValue::VARR);
std::map<std::string, tallyitem> label_tally;
- // Create m_address_book iterator
- // If we aren't filtering, go from begin() to end()
- auto start = wallet.m_address_book.begin();
- auto end = wallet.m_address_book.end();
- // If we are filtering, find() the applicable entry
- if (has_filtered_address) {
- start = wallet.m_address_book.find(filtered_address);
- if (start != end) {
- end = std::next(start);
- }
- }
+ const auto& func = [&](const CTxDestination& address, const std::string& label, const std::string& purpose, bool is_change) {
+ if (is_change) return; // no change addresses
- for (auto item_it = start; item_it != end; ++item_it)
- {
- if (item_it->second.IsChange()) continue;
- const CTxDestination& address = item_it->first;
- const std::string& label = item_it->second.GetLabel();
auto it = mapTally.find(address);
if (it == mapTally.end() && !fIncludeEmpty)
- continue;
+ return;
CAmount nAmount = 0;
int nConf = std::numeric_limits<int>::max();
bool fIsWatchonly = false;
- if (it != mapTally.end())
- {
+ if (it != mapTally.end()) {
nAmount = (*it).second.nAmount;
nConf = (*it).second.nConf;
fIsWatchonly = (*it).second.fIsWatchonly;
}
- if (by_label)
- {
+ if (by_label) {
tallyitem& _item = label_tally[label];
_item.nAmount += nAmount;
_item.nConf = std::min(_item.nConf, nConf);
_item.fIsWatchonly = fIsWatchonly;
- }
- else
- {
+ } else {
UniValue obj(UniValue::VOBJ);
- if(fIsWatchonly)
- obj.pushKV("involvesWatchonly", true);
+ if (fIsWatchonly) obj.pushKV("involvesWatchonly", true);
obj.pushKV("address", EncodeDestination(address));
obj.pushKV("amount", ValueFromAmount(nAmount));
obj.pushKV("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf));
obj.pushKV("label", label);
UniValue transactions(UniValue::VARR);
- if (it != mapTally.end())
- {
- for (const uint256& _item : (*it).second.txids)
- {
+ if (it != mapTally.end()) {
+ for (const uint256& _item : (*it).second.txids) {
transactions.push_back(_item.GetHex());
}
}
obj.pushKV("txids", transactions);
ret.push_back(obj);
}
+ };
+
+ if (filtered_address) {
+ const auto& entry = wallet.FindAddressBookEntry(*filtered_address, /*allow_change=*/false);
+ if (entry) func(*filtered_address, entry->GetLabel(), entry->purpose, /*is_change=*/false);
+ } else {
+ // No filtered addr, walk-through the addressbook entry
+ wallet.ForEachAddrBookEntry(func);
}
- if (by_label)
- {
- for (const auto& entry : label_tally)
- {
+ if (by_label) {
+ for (const auto& entry : label_tally) {
CAmount nAmount = entry.second.nAmount;
int nConf = entry.second.nConf;
UniValue obj(UniValue::VOBJ);
@@ -255,7 +236,7 @@ RPCHelpMan listreceivedbyaddress()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -300,7 +281,7 @@ RPCHelpMan listreceivedbylabel()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -329,17 +310,21 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
* @param wtx The wallet transaction.
* @param nMinDepth The minimum confirmation depth.
* @param fLong Whether to include the JSON version of the transaction.
- * @param ret The UniValue into which the result is stored.
+ * @param ret The vector into which the result is stored.
* @param filter_ismine The "is mine" filter flags.
* @param filter_label Optional label string to filter incoming transactions.
*/
-static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
+template <class Vec>
+static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong,
+ Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label,
+ bool include_change = false)
+ EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
CAmount nFee;
std::list<COutputEntry> listReceived;
std::list<COutputEntry> listSent;
- CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, filter_ismine);
+ CachedTxGetAmounts(wallet, wtx, listReceived, listSent, nFee, filter_ismine, include_change);
bool involvesWatchonly = CachedTxIsFromMe(wallet, wtx, ISMINE_WATCH_ONLY);
@@ -385,6 +370,7 @@ static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nM
entry.pushKV("involvesWatchonly", true);
}
MaybePushAddress(entry, r.destination);
+ PushParentDescriptors(wallet, wtx.tx->vout.at(r.vout).scriptPubKey, entry);
if (wtx.IsCoinBase())
{
if (wallet.GetTxDepthInMainChain(wtx) < 1)
@@ -435,8 +421,12 @@ static const std::vector<RPCResult> TransactionDescriptionString()
{RPCResult::Type::NUM_TIME, "time", "The transaction time expressed in " + UNIX_EPOCH_TIME + "."},
{RPCResult::Type::NUM_TIME, "timereceived", "The time received expressed in " + UNIX_EPOCH_TIME + "."},
{RPCResult::Type::STR, "comment", /*optional=*/true, "If a comment is associated with the transaction, only present if not empty."},
- {RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
- "may be unknown for unconfirmed transactions not in the mempool."}};
+ {RPCResult::Type::STR, "bip125-replaceable", "(\"yes|no|unknown\") Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability.\n"
+ "May be unknown for unconfirmed transactions not in the mempool because their unconfirmed ancestors are unknown."},
+ {RPCResult::Type::ARR, "parent_descs", /*optional=*/true, "Only if 'category' is 'received'. List of parent descriptors for the scriptPubKey of this coin.", {
+ {RPCResult::Type::STR, "desc", "The descriptor string."},
+ }},
+ };
}
RPCHelpMan listtransactions()
@@ -457,7 +447,7 @@ RPCHelpMan listtransactions()
{RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
{
{RPCResult::Type::BOOL, "involvesWatchonly", /*optional=*/true, "Only returns true if imported addresses were involved in transaction."},
- {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "The bitcoin address of the transaction (not returned if the output does not have an address, e.g. OP_RETURN null data)."},
{RPCResult::Type::STR, "category", "The transaction category.\n"
"\"send\" Transactions sent.\n"
"\"receive\" Non-coinbase transactions received.\n"
@@ -489,7 +479,7 @@ RPCHelpMan listtransactions()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -519,8 +509,7 @@ RPCHelpMan listtransactions()
if (nFrom < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
- UniValue ret(UniValue::VARR);
-
+ std::vector<UniValue> ret;
{
LOCK(pwallet->cs_wallet);
@@ -542,9 +531,9 @@ RPCHelpMan listtransactions()
if ((nFrom + nCount) > (int)ret.size())
nCount = ret.size() - nFrom;
- const std::vector<UniValue>& txs = ret.getValues();
+ auto txs_rev_it{std::make_move_iterator(ret.rend())};
UniValue result{UniValue::VARR};
- result.push_backV({ txs.rend() - nFrom - nCount, txs.rend() - nFrom }); // Return oldest to newest
+ result.push_backV(txs_rev_it - nFrom - nCount, txs_rev_it - nFrom); // Return oldest to newest
return result;
},
};
@@ -562,6 +551,7 @@ RPCHelpMan listsinceblock()
{"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Include transactions to watch-only addresses (see 'importaddress')"},
{"include_removed", RPCArg::Type::BOOL, RPCArg::Default{true}, "Show transactions that were removed due to a reorg in the \"removed\" array\n"
"(not guaranteed to work on pruned nodes)"},
+ {"include_change", RPCArg::Type::BOOL, RPCArg::Default{false}, "Also add entries for change outputs.\n"},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -571,7 +561,7 @@ RPCHelpMan listsinceblock()
{RPCResult::Type::OBJ, "", "", Cat(Cat<std::vector<RPCResult>>(
{
{RPCResult::Type::BOOL, "involvesWatchonly", /*optional=*/true, "Only returns true if imported addresses were involved in transaction."},
- {RPCResult::Type::STR, "address", "The bitcoin address of the transaction."},
+ {RPCResult::Type::STR, "address", /*optional=*/true, "The bitcoin address of the transaction (not returned if the output does not have an address, e.g. OP_RETURN null data)."},
{RPCResult::Type::STR, "category", "The transaction category.\n"
"\"send\" Transactions sent.\n"
"\"receive\" Non-coinbase transactions received.\n"
@@ -605,7 +595,7 @@ RPCHelpMan listsinceblock()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
const CWallet& wallet = *pwallet;
// Make sure the results are valid at least up to the most recent block
@@ -642,6 +632,7 @@ RPCHelpMan listsinceblock()
}
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
+ bool include_change = (!request.params[4].isNull() && request.params[4].get_bool());
int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1;
@@ -651,7 +642,7 @@ RPCHelpMan listsinceblock()
const CWalletTx& tx = pairWtx.second;
if (depth == -1 || abs(wallet.GetTxDepthInMainChain(tx)) < depth) {
- ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
+ ListTransactions(wallet, tx, 0, true, transactions, filter, nullptr /* filter_label */, /*include_change=*/include_change);
}
}
@@ -668,7 +659,7 @@ RPCHelpMan listsinceblock()
if (it != wallet.mapWallet.end()) {
// We want all transactions regardless of confirmation count to appear here,
// even negative confirmation ones, hence the big negative.
- ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */);
+ ListTransactions(wallet, it->second, -100000000, true, removed, filter, nullptr /* filter_label */, /*include_change=*/include_change);
}
}
blockId = block.hashPrevBlock;
@@ -728,6 +719,9 @@ RPCHelpMan gettransaction()
"'send' category of transactions."},
{RPCResult::Type::BOOL, "abandoned", /*optional=*/true, "'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n"
"'send' category of transactions."},
+ {RPCResult::Type::ARR, "parent_descs", /*optional=*/true, "Only if 'category' is 'received'. List of parent descriptors for the scriptPubKey of this coin.", {
+ {RPCResult::Type::STR, "desc", "The descriptor string."},
+ }},
}},
}},
{RPCResult::Type::STR_HEX, "hex", "Raw data for transaction"},
@@ -746,7 +740,7 @@ RPCHelpMan gettransaction()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -819,7 +813,7 @@ RPCHelpMan abandontransaction()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -836,7 +830,7 @@ RPCHelpMan abandontransaction()
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
}
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -864,7 +858,7 @@ RPCHelpMan rescanblockchain()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
CWallet& wallet{*pwallet};
// Make sure the results are valid at least up to the most recent block
@@ -908,7 +902,7 @@ RPCHelpMan rescanblockchain()
}
CWallet::ScanResult result =
- pwallet->ScanForWalletTransactions(start_block, start_height, stop_height, reserver, true /* fUpdate */);
+ pwallet->ScanForWalletTransactions(start_block, start_height, stop_height, reserver, /*fUpdate=*/true, /*save_progress=*/false);
switch (result.status) {
case CWallet::ScanResult::SUCCESS:
break;
@@ -944,7 +938,7 @@ RPCHelpMan abortrescan()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
pwallet->AbortRescan();
diff --git a/src/wallet/rpc/util.cpp b/src/wallet/rpc/util.cpp
index 4fcb393226..3c1634324e 100644
--- a/src/wallet/rpc/util.cpp
+++ b/src/wallet/rpc/util.cpp
@@ -64,12 +64,11 @@ std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& reques
return pwallet;
}
- std::vector<std::shared_ptr<CWallet>> wallets = GetWallets(context);
- if (wallets.size() == 1) {
- return wallets[0];
- }
+ size_t count{0};
+ auto wallet = GetDefaultWallet(context, count);
+ if (wallet) return wallet;
- if (wallets.empty()) {
+ if (count == 0) {
throw JSONRPCError(
RPC_WALLET_NOT_FOUND, "No wallet is loaded. Load a wallet using loadwallet or create a new one with createwallet. (Note: A default wallet is no longer automatically created)");
}
@@ -123,6 +122,15 @@ std::string LabelFromValue(const UniValue& value)
return label;
}
+void PushParentDescriptors(const CWallet& wallet, const CScript& script_pubkey, UniValue& entry)
+{
+ UniValue parent_descs(UniValue::VARR);
+ for (const auto& desc: wallet.GetWalletDescriptors(script_pubkey)) {
+ parent_descs.push_back(desc.descriptor->ToString());
+ }
+ entry.pushKV("parent_descs", parent_descs);
+}
+
void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error)
{
if (!wallet) {
diff --git a/src/wallet/rpc/util.h b/src/wallet/rpc/util.h
index 7b810eb06e..2ca28914e7 100644
--- a/src/wallet/rpc/util.h
+++ b/src/wallet/rpc/util.h
@@ -5,6 +5,8 @@
#ifndef BITCOIN_WALLET_RPC_UTIL_H
#define BITCOIN_WALLET_RPC_UTIL_H
+#include <script/script.h>
+
#include <any>
#include <memory>
#include <string>
@@ -39,6 +41,8 @@ const LegacyScriptPubKeyMan& EnsureConstLegacyScriptPubKeyMan(const CWallet& wal
bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param);
bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet);
std::string LabelFromValue(const UniValue& value);
+//! Fetch parent descriptors of this scriptPubKey.
+void PushParentDescriptors(const CWallet& wallet, const CScript& script_pubkey, UniValue& entry);
void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error);
} // namespace wallet
diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 4c44c333a6..971814e9cd 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -68,7 +68,7 @@ static RPCHelpMan getwalletinfo()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
@@ -241,7 +241,7 @@ static RPCHelpMan loadwallet()
static RPCHelpMan setwalletflag()
{
- std::string flags = "";
+ std::string flags;
for (auto& it : WALLET_FLAG_MAP)
if (it.second & MUTABLE_WALLET_FLAGS)
flags += (flags == "" ? "" : ", ") + it.first;
@@ -267,7 +267,7 @@ static RPCHelpMan setwalletflag()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
std::string flag_str = request.params[0].get_str();
bool value = request.params[1].isNull() || request.params[1].get_bool();
@@ -480,7 +480,7 @@ static RPCHelpMan sethdseed()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*pwallet, true);
@@ -521,7 +521,7 @@ static RPCHelpMan sethdseed()
spk_man.SetHDSeed(master_pub_key);
if (flush_key_pool) spk_man.NewKeyPool();
- return NullUniValue;
+ return UniValue::VNULL;
},
};
}
@@ -532,7 +532,7 @@ static RPCHelpMan upgradewallet()
"\nUpgrade the wallet. Upgrades to the latest version if no version number is specified.\n"
"New keys may be generated and a new wallet backup will need to be made.",
{
- {"version", RPCArg::Type::NUM, RPCArg::Default{FEATURE_LATEST}, "The version number to upgrade to. Default is the latest wallet version."}
+ {"version", RPCArg::Type::NUM, RPCArg::Default{int{FEATURE_LATEST}}, "The version number to upgrade to. Default is the latest wallet version."}
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -551,7 +551,7 @@ static RPCHelpMan upgradewallet()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
- if (!pwallet) return NullUniValue;
+ if (!pwallet) return UniValue::VNULL;
RPCTypeCheck(request.params, {UniValue::VNUM}, true);
@@ -590,6 +590,172 @@ static RPCHelpMan upgradewallet()
};
}
+RPCHelpMan simulaterawtransaction()
+{
+ return RPCHelpMan{"simulaterawtransaction",
+ "\nCalculate the balance change resulting in the signing and broadcasting of the given transaction(s).\n",
+ {
+ {"rawtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "An array of hex strings of raw transactions.\n",
+ {
+ {"rawtx", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
+ },
+ },
+ {"options", RPCArg::Type::OBJ_USER_KEYS, RPCArg::Optional::OMITTED_NAMED_ARG, "Options",
+ {
+ {"include_watchonly", RPCArg::Type::BOOL, RPCArg::DefaultHint{"true for watch-only wallets, otherwise false"}, "Whether to include watch-only addresses (see RPC importaddress)"},
+ },
+ },
+ },
+ RPCResult{
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR_AMOUNT, "balance_change", "The wallet balance change (negative means decrease)."},
+ }
+ },
+ RPCExamples{
+ HelpExampleCli("simulaterawtransaction", "[\"myhex\"]")
+ + HelpExampleRpc("simulaterawtransaction", "[\"myhex\"]")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+{
+ const std::shared_ptr<const CWallet> rpc_wallet = GetWalletForJSONRPCRequest(request);
+ if (!rpc_wallet) return UniValue::VNULL;
+ const CWallet& wallet = *rpc_wallet;
+
+ RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ}, true);
+
+ LOCK(wallet.cs_wallet);
+
+ UniValue include_watchonly(UniValue::VNULL);
+ if (request.params[1].isObject()) {
+ UniValue options = request.params[1];
+ RPCTypeCheckObj(options,
+ {
+ {"include_watchonly", UniValueType(UniValue::VBOOL)},
+ },
+ true, true);
+
+ include_watchonly = options["include_watchonly"];
+ }
+
+ isminefilter filter = ISMINE_SPENDABLE;
+ if (ParseIncludeWatchonly(include_watchonly, wallet)) {
+ filter |= ISMINE_WATCH_ONLY;
+ }
+
+ const auto& txs = request.params[0].get_array();
+ CAmount changes{0};
+ std::map<COutPoint, CAmount> new_utxos; // UTXO:s that were made available in transaction array
+ std::set<COutPoint> spent;
+
+ for (size_t i = 0; i < txs.size(); ++i) {
+ CMutableTransaction mtx;
+ if (!DecodeHexTx(mtx, txs[i].get_str(), /* try_no_witness */ true, /* try_witness */ true)) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Transaction hex string decoding failure.");
+ }
+
+ // Fetch previous transactions (inputs)
+ std::map<COutPoint, Coin> coins;
+ for (const CTxIn& txin : mtx.vin) {
+ coins[txin.prevout]; // Create empty map entry keyed by prevout.
+ }
+ wallet.chain().findCoins(coins);
+
+ // Fetch debit; we are *spending* these; if the transaction is signed and
+ // broadcast, we will lose everything in these
+ for (const auto& txin : mtx.vin) {
+ const auto& outpoint = txin.prevout;
+ if (spent.count(outpoint)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Transaction(s) are spending the same output more than once");
+ }
+ if (new_utxos.count(outpoint)) {
+ changes -= new_utxos.at(outpoint);
+ new_utxos.erase(outpoint);
+ } else {
+ if (coins.at(outpoint).IsSpent()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more transaction inputs are missing or have been spent already");
+ }
+ changes -= wallet.GetDebit(txin, filter);
+ }
+ spent.insert(outpoint);
+ }
+
+ // Iterate over outputs; we are *receiving* these, if the wallet considers
+ // them "mine"; if the transaction is signed and broadcast, we will receive
+ // everything in these
+ // Also populate new_utxos in case these are spent in later transactions
+
+ const auto& hash = mtx.GetHash();
+ for (size_t i = 0; i < mtx.vout.size(); ++i) {
+ const auto& txout = mtx.vout[i];
+ bool is_mine = 0 < (wallet.IsMine(txout) & filter);
+ changes += new_utxos[COutPoint(hash, i)] = is_mine ? txout.nValue : 0;
+ }
+ }
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("balance_change", ValueFromAmount(changes));
+
+ return result;
+}
+ };
+}
+
+static RPCHelpMan migratewallet()
+{
+ return RPCHelpMan{"migratewallet",
+ "EXPERIMENTAL warning: This call may not work as expected and may be changed in future releases\n"
+ "\nMigrate the wallet to a descriptor wallet.\n"
+ "A new wallet backup will need to be made.\n"
+ "\nThe migration process will create a backup of the wallet before migrating. This backup\n"
+ "file will be named <wallet name>-<timestamp>.legacy.bak and can be found in the directory\n"
+ "for this wallet. In the event of an incorrect migration, the backup can be restored using restorewallet." +
+ HELP_REQUIRING_PASSPHRASE,
+ {},
+ RPCResult{
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "wallet_name", "The name of the primary migrated wallet"},
+ {RPCResult::Type::STR, "watchonly_name", /*optional=*/true, "The name of the migrated wallet containing the watchonly scripts"},
+ {RPCResult::Type::STR, "solvables_name", /*optional=*/true, "The name of the migrated wallet containing solvable but not watched scripts"},
+ {RPCResult::Type::STR, "backup_path", "The location of the backup of the original wallet"},
+ }
+ },
+ RPCExamples{
+ HelpExampleCli("migratewallet", "")
+ + HelpExampleRpc("migratewallet", "")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+ {
+ std::shared_ptr<CWallet> wallet = GetWalletForJSONRPCRequest(request);
+ if (!wallet) return NullUniValue;
+
+ if (wallet->IsCrypted()) {
+ throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: migratewallet on encrypted wallets is currently unsupported.");
+ }
+
+ WalletContext& context = EnsureWalletContext(request.context);
+
+ util::Result<MigrationResult> res = MigrateLegacyToDescriptor(std::move(wallet), context);
+ if (!res) {
+ throw JSONRPCError(RPC_WALLET_ERROR, util::ErrorString(res).original);
+ }
+
+ UniValue r{UniValue::VOBJ};
+ r.pushKV("wallet_name", res->wallet_name);
+ if (res->watchonly_wallet) {
+ r.pushKV("watchonly_name", res->watchonly_wallet->GetName());
+ }
+ if (res->solvables_wallet) {
+ r.pushKV("solvables_name", res->solvables_wallet->GetName());
+ }
+ r.pushKV("backup_path", res->backup_path.u8string());
+
+ return r;
+ },
+ };
+}
+
// addresses
RPCHelpMan getaddressinfo();
RPCHelpMan getnewaddress();
@@ -709,6 +875,7 @@ Span<const CRPCCommand> GetWalletRPCCommands()
{"wallet", &listwallets},
{"wallet", &loadwallet},
{"wallet", &lockunspent},
+ {"wallet", &migratewallet},
{"wallet", &newkeypool},
{"wallet", &removeprunedfunds},
{"wallet", &rescanblockchain},
@@ -721,6 +888,7 @@ Span<const CRPCCommand> GetWalletRPCCommands()
{"wallet", &setwalletflag},
{"wallet", &signmessage},
{"wallet", &signrawtransactionwithwallet},
+ {"wallet", &simulaterawtransaction},
{"wallet", &sendall},
{"wallet", &unloadwallet},
{"wallet", &upgradewallet},
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 8633e7c62c..3bcc6b4bdc 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -21,26 +21,22 @@ namespace wallet {
//! Value for the first BIP 32 hardened derivation. Can be used as a bit mask and as a value. See BIP 32 for more details.
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
-bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error)
+util::Result<CTxDestination> LegacyScriptPubKeyMan::GetNewDestination(const OutputType type)
{
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
- error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");
- return false;
+ return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
}
assert(type != OutputType::BECH32M);
LOCK(cs_KeyStore);
- error.clear();
// Generate a new key that is added to wallet
CPubKey new_key;
if (!GetKeyFromPool(new_key, type)) {
- error = _("Error: Keypool ran out, please call keypoolrefill first");
- return false;
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
LearnRelatedScripts(new_key, type);
- dest = GetDestinationForKey(new_key, type);
- return true;
+ return GetDestinationForKey(new_key, type);
}
typedef std::vector<unsigned char> valtype;
@@ -296,26 +292,22 @@ bool LegacyScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, WalletBat
return true;
}
-bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
+util::Result<CTxDestination> LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
{
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
- error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");
- return false;
+ return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
}
assert(type != OutputType::BECH32M);
LOCK(cs_KeyStore);
if (!CanGetAddresses(internal)) {
- error = _("Error: Keypool ran out, please call keypoolrefill first");
- return false;
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
- error = _("Error: Keypool ran out, please call keypoolrefill first");
- return false;
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
- address = GetDestinationForKey(keypool.vchPubKey, type);
- return true;
+ return GetDestinationForKey(keypool.vchPubKey, type);
}
bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal)
@@ -1007,9 +999,10 @@ bool LegacyScriptPubKeyMan::GetKeyOrigin(const CKeyID& keyID, KeyOriginInfo& inf
{
LOCK(cs_KeyStore);
auto it = mapKeyMetadata.find(keyID);
- if (it != mapKeyMetadata.end()) {
- meta = it->second;
+ if (it == mapKeyMetadata.end()) {
+ return false;
}
+ meta = it->second;
}
if (meta.has_key_origin) {
std::copy(meta.key_origin.fingerprint, meta.key_origin.fingerprint + 4, info.fingerprint);
@@ -1088,6 +1081,13 @@ CPubKey LegacyScriptPubKeyMan::GenerateNewKey(WalletBatch &batch, CHDChain& hd_c
return pubkey;
}
+//! Try to derive an extended key, throw if it fails.
+static void DeriveExtKey(CExtKey& key_in, unsigned int index, CExtKey& key_out) {
+ if (!key_in.Derive(key_out, index)) {
+ throw std::runtime_error("Could not derive extended key");
+ }
+}
+
void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, CHDChain& hd_chain, bool internal)
{
// for now we use a fixed keypath scheme of m/0'/0'/k
@@ -1105,11 +1105,11 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
// derive m/0'
// use hardened derivation (child keys >= 0x80000000 are hardened after bip32)
- masterKey.Derive(accountKey, BIP32_HARDENED_KEY_LIMIT);
+ DeriveExtKey(masterKey, BIP32_HARDENED_KEY_LIMIT, accountKey);
// derive m/0'/0' (external chain) OR m/0'/1' (internal chain)
assert(internal ? m_storage.CanSupportFeature(FEATURE_HD_SPLIT) : true);
- accountKey.Derive(chainChildKey, BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0));
+ DeriveExtKey(accountKey, BIP32_HARDENED_KEY_LIMIT+(internal ? 1 : 0), chainChildKey);
// derive child key at next index, skip keys already known to the wallet
do {
@@ -1117,7 +1117,7 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
// childIndex | BIP32_HARDENED_KEY_LIMIT = derive childIndex in hardened child-index-range
// example: 1 | BIP32_HARDENED_KEY_LIMIT == 0x80000001 == 2147483649
if (internal) {
- chainChildKey.Derive(childKey, hd_chain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
+ DeriveExtKey(chainChildKey, hd_chain.nInternalChainCounter | BIP32_HARDENED_KEY_LIMIT, childKey);
metadata.hdKeypath = "m/0'/1'/" + ToString(hd_chain.nInternalChainCounter) + "'";
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
metadata.key_origin.path.push_back(1 | BIP32_HARDENED_KEY_LIMIT);
@@ -1125,7 +1125,7 @@ void LegacyScriptPubKeyMan::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata&
hd_chain.nInternalChainCounter++;
}
else {
- chainChildKey.Derive(childKey, hd_chain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT);
+ DeriveExtKey(chainChildKey, hd_chain.nExternalChainCounter | BIP32_HARDENED_KEY_LIMIT, childKey);
metadata.hdKeypath = "m/0'/0'/" + ToString(hd_chain.nExternalChainCounter) + "'";
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
metadata.key_origin.path.push_back(0 | BIP32_HARDENED_KEY_LIMIT);
@@ -1457,7 +1457,8 @@ void LegacyScriptPubKeyMan::LearnRelatedScripts(const CPubKey& key, OutputType t
CTxDestination witdest = WitnessV0KeyHash(key.GetID());
CScript witprog = GetScriptForDestination(witdest);
// Make sure the resulting program is solvable.
- assert(IsSolvable(*this, witprog));
+ const auto desc = InferDescriptor(witprog, *this);
+ assert(desc && desc->IsSolvable());
AddCScript(witprog);
}
}
@@ -1658,12 +1659,323 @@ std::set<CKeyID> LegacyScriptPubKeyMan::GetKeys() const
return set_address;
}
-bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error)
+const std::unordered_set<CScript, SaltedSipHasher> LegacyScriptPubKeyMan::GetScriptPubKeys() const
+{
+ LOCK(cs_KeyStore);
+ std::unordered_set<CScript, SaltedSipHasher> spks;
+
+ // All keys have at least P2PK and P2PKH
+ for (const auto& key_pair : mapKeys) {
+ const CPubKey& pub = key_pair.second.GetPubKey();
+ spks.insert(GetScriptForRawPubKey(pub));
+ spks.insert(GetScriptForDestination(PKHash(pub)));
+ }
+ for (const auto& key_pair : mapCryptedKeys) {
+ const CPubKey& pub = key_pair.second.first;
+ spks.insert(GetScriptForRawPubKey(pub));
+ spks.insert(GetScriptForDestination(PKHash(pub)));
+ }
+
+ // For every script in mapScript, only the ISMINE_SPENDABLE ones are being tracked.
+ // The watchonly ones will be in setWatchOnly which we deal with later
+ // For all keys, if they have segwit scripts, those scripts will end up in mapScripts
+ for (const auto& script_pair : mapScripts) {
+ const CScript& script = script_pair.second;
+ if (IsMine(script) == ISMINE_SPENDABLE) {
+ // Add ScriptHash for scripts that are not already P2SH
+ if (!script.IsPayToScriptHash()) {
+ spks.insert(GetScriptForDestination(ScriptHash(script)));
+ }
+ // For segwit scripts, we only consider them spendable if we have the segwit spk
+ int wit_ver = -1;
+ std::vector<unsigned char> witprog;
+ if (script.IsWitnessProgram(wit_ver, witprog) && wit_ver == 0) {
+ spks.insert(script);
+ }
+ } else {
+ // Multisigs are special. They don't show up as ISMINE_SPENDABLE unless they are in a P2SH
+ // So check the P2SH of a multisig to see if we should insert it
+ std::vector<std::vector<unsigned char>> sols;
+ TxoutType type = Solver(script, sols);
+ if (type == TxoutType::MULTISIG) {
+ CScript ms_spk = GetScriptForDestination(ScriptHash(script));
+ if (IsMine(ms_spk) != ISMINE_NO) {
+ spks.insert(ms_spk);
+ }
+ }
+ }
+ }
+
+ // All watchonly scripts are raw
+ spks.insert(setWatchOnly.begin(), setWatchOnly.end());
+
+ return spks;
+}
+
+std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()
+{
+ LOCK(cs_KeyStore);
+ if (m_storage.IsLocked()) {
+ return std::nullopt;
+ }
+
+ MigrationData out;
+
+ std::unordered_set<CScript, SaltedSipHasher> spks{GetScriptPubKeys()};
+
+ // Get all key ids
+ std::set<CKeyID> keyids;
+ for (const auto& key_pair : mapKeys) {
+ keyids.insert(key_pair.first);
+ }
+ for (const auto& key_pair : mapCryptedKeys) {
+ keyids.insert(key_pair.first);
+ }
+
+ // Get key metadata and figure out which keys don't have a seed
+ // Note that we do not ignore the seeds themselves because they are considered IsMine!
+ for (auto keyid_it = keyids.begin(); keyid_it != keyids.end();) {
+ const CKeyID& keyid = *keyid_it;
+ const auto& it = mapKeyMetadata.find(keyid);
+ if (it != mapKeyMetadata.end()) {
+ const CKeyMetadata& meta = it->second;
+ if (meta.hdKeypath == "s" || meta.hdKeypath == "m") {
+ keyid_it++;
+ continue;
+ }
+ if (m_hd_chain.seed_id == meta.hd_seed_id || m_inactive_hd_chains.count(meta.hd_seed_id) > 0) {
+ keyid_it = keyids.erase(keyid_it);
+ continue;
+ }
+ }
+ keyid_it++;
+ }
+
+ // keyids is now all non-HD keys. Each key will have its own combo descriptor
+ for (const CKeyID& keyid : keyids) {
+ CKey key;
+ if (!GetKey(keyid, key)) {
+ assert(false);
+ }
+
+ // Get birthdate from key meta
+ uint64_t creation_time = 0;
+ const auto& it = mapKeyMetadata.find(keyid);
+ if (it != mapKeyMetadata.end()) {
+ creation_time = it->second.nCreateTime;
+ }
+
+ // Get the key origin
+ // Maybe this doesn't matter because floating keys here shouldn't have origins
+ KeyOriginInfo info;
+ bool has_info = GetKeyOrigin(keyid, info);
+ std::string origin_str = has_info ? "[" + HexStr(info.fingerprint) + FormatHDKeypath(info.path) + "]" : "";
+
+ // Construct the combo descriptor
+ std::string desc_str = "combo(" + origin_str + HexStr(key.GetPubKey()) + ")";
+ FlatSigningProvider keys;
+ std::string error;
+ std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, error, false);
+ WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
+
+ // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
+ auto desc_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(m_storage, w_desc));
+ desc_spk_man->AddDescriptorKey(key, key.GetPubKey());
+ desc_spk_man->TopUp();
+ auto desc_spks = desc_spk_man->GetScriptPubKeys();
+
+ // Remove the scriptPubKeys from our current set
+ for (const CScript& spk : desc_spks) {
+ size_t erased = spks.erase(spk);
+ assert(erased == 1);
+ assert(IsMine(spk) == ISMINE_SPENDABLE);
+ }
+
+ out.desc_spkms.push_back(std::move(desc_spk_man));
+ }
+
+ // Handle HD keys by using the CHDChains
+ std::vector<CHDChain> chains;
+ chains.push_back(m_hd_chain);
+ for (const auto& chain_pair : m_inactive_hd_chains) {
+ chains.push_back(chain_pair.second);
+ }
+ for (const CHDChain& chain : chains) {
+ for (int i = 0; i < 2; ++i) {
+ // Skip if doing internal chain and split chain is not supported
+ if (chain.seed_id.IsNull() || (i == 1 && !m_storage.CanSupportFeature(FEATURE_HD_SPLIT))) {
+ continue;
+ }
+ // Get the master xprv
+ CKey seed_key;
+ if (!GetKey(chain.seed_id, seed_key)) {
+ assert(false);
+ }
+ CExtKey master_key;
+ master_key.SetSeed(seed_key);
+
+ // Make the combo descriptor
+ std::string xpub = EncodeExtPubKey(master_key.Neuter());
+ std::string desc_str = "combo(" + xpub + "/0'/" + ToString(i) + "'/*')";
+ FlatSigningProvider keys;
+ std::string error;
+ std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, error, false);
+ uint32_t chain_counter = std::max((i == 1 ? chain.nInternalChainCounter : chain.nExternalChainCounter), (uint32_t)0);
+ WalletDescriptor w_desc(std::move(desc), 0, 0, chain_counter, 0);
+
+ // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
+ auto desc_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(m_storage, w_desc));
+ desc_spk_man->AddDescriptorKey(master_key.key, master_key.key.GetPubKey());
+ desc_spk_man->TopUp();
+ auto desc_spks = desc_spk_man->GetScriptPubKeys();
+
+ // Remove the scriptPubKeys from our current set
+ for (const CScript& spk : desc_spks) {
+ size_t erased = spks.erase(spk);
+ assert(erased == 1);
+ assert(IsMine(spk) == ISMINE_SPENDABLE);
+ }
+
+ out.desc_spkms.push_back(std::move(desc_spk_man));
+ }
+ }
+ // Add the current master seed to the migration data
+ if (!m_hd_chain.seed_id.IsNull()) {
+ CKey seed_key;
+ if (!GetKey(m_hd_chain.seed_id, seed_key)) {
+ assert(false);
+ }
+ out.master_key.SetSeed(seed_key);
+ }
+
+ // Handle the rest of the scriptPubKeys which must be imports and may not have all info
+ for (auto it = spks.begin(); it != spks.end();) {
+ const CScript& spk = *it;
+
+ // Get birthdate from script meta
+ uint64_t creation_time = 0;
+ const auto& mit = m_script_metadata.find(CScriptID(spk));
+ if (mit != m_script_metadata.end()) {
+ creation_time = mit->second.nCreateTime;
+ }
+
+ // InferDescriptor as that will get us all the solving info if it is there
+ std::unique_ptr<Descriptor> desc = InferDescriptor(spk, *GetSolvingProvider(spk));
+ // Get the private keys for this descriptor
+ std::vector<CScript> scripts;
+ FlatSigningProvider keys;
+ if (!desc->Expand(0, DUMMY_SIGNING_PROVIDER, scripts, keys)) {
+ assert(false);
+ }
+ std::set<CKeyID> privkeyids;
+ for (const auto& key_orig_pair : keys.origins) {
+ privkeyids.insert(key_orig_pair.first);
+ }
+
+ std::vector<CScript> desc_spks;
+
+ // Make the descriptor string with private keys
+ 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});
+
+ // Get the scriptPubKeys without writing this to the wallet
+ FlatSigningProvider provider;
+ desc->Expand(0, provider, desc_spks, provider);
+ } else {
+ // Make the DescriptorScriptPubKeyMan and get the scriptPubKeys
+ WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
+ auto desc_spk_man = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(m_storage, w_desc));
+ for (const auto& keyid : privkeyids) {
+ CKey key;
+ if (!GetKey(keyid, key)) {
+ continue;
+ }
+ desc_spk_man->AddDescriptorKey(key, key.GetPubKey());
+ }
+ desc_spk_man->TopUp();
+ auto desc_spks_set = desc_spk_man->GetScriptPubKeys();
+ desc_spks.insert(desc_spks.end(), desc_spks_set.begin(), desc_spks_set.end());
+
+ out.desc_spkms.push_back(std::move(desc_spk_man));
+ }
+
+ // Remove the scriptPubKeys from our current set
+ for (const CScript& desc_spk : desc_spks) {
+ auto del_it = spks.find(desc_spk);
+ assert(del_it != spks.end());
+ assert(IsMine(desc_spk) != ISMINE_NO);
+ it = spks.erase(del_it);
+ }
+ }
+
+ // Multisigs are special. They don't show up as ISMINE_SPENDABLE unless they are in a P2SH
+ // So we have to check if any of our scripts are a multisig and if so, add the P2SH
+ for (const auto& script_pair : mapScripts) {
+ const CScript script = script_pair.second;
+
+ // Get birthdate from script meta
+ uint64_t creation_time = 0;
+ const auto& it = m_script_metadata.find(CScriptID(script));
+ if (it != m_script_metadata.end()) {
+ creation_time = it->second.nCreateTime;
+ }
+
+ std::vector<std::vector<unsigned char>> sols;
+ TxoutType type = Solver(script, sols);
+ if (type == TxoutType::MULTISIG) {
+ CScript sh_spk = GetScriptForDestination(ScriptHash(script));
+ CTxDestination witdest = WitnessV0ScriptHash(script);
+ CScript witprog = GetScriptForDestination(witdest);
+ CScript sh_wsh_spk = GetScriptForDestination(ScriptHash(witprog));
+
+ // We only want the multisigs that we have not already seen, i.e. they are not watchonly and not spendable
+ // For P2SH, a multisig is not ISMINE_NO when:
+ // * All keys are in the wallet
+ // * The multisig itself is watch only
+ // * The P2SH is watch only
+ // For P2SH-P2WSH, if the script is in the wallet, then it will have the same conditions as P2SH.
+ // For P2WSH, a multisig is not ISMINE_NO when, other than the P2SH conditions:
+ // * The P2WSH script is in the wallet and it is being watched
+ std::vector<std::vector<unsigned char>> keys(sols.begin() + 1, sols.begin() + sols.size() - 1);
+ if (HaveWatchOnly(sh_spk) || HaveWatchOnly(script) || HaveKeys(keys, *this) || (HaveCScript(CScriptID(witprog)) && HaveWatchOnly(witprog))) {
+ // The above emulates IsMine for these 3 scriptPubKeys, so double check that by running IsMine
+ assert(IsMine(sh_spk) != ISMINE_NO || IsMine(witprog) != ISMINE_NO || IsMine(sh_wsh_spk) != ISMINE_NO);
+ continue;
+ }
+ 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});
+
+ 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});
+ 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});
+ }
+ }
+ }
+
+ // Make sure that we have accounted for all scriptPubKeys
+ assert(spks.size() == 0);
+ return out;
+}
+
+bool LegacyScriptPubKeyMan::DeleteRecords()
+{
+ LOCK(cs_KeyStore);
+ WalletBatch batch(m_storage.GetDatabase());
+ return batch.EraseRecords(DBKeys::LEGACY_TYPES);
+}
+
+util::Result<CTxDestination> DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type)
{
// Returns true if this descriptor supports getting new addresses. Conditions where we may be unable to fetch them (e.g. locked) are caught later
if (!CanGetAddresses()) {
- error = _("No addresses available");
- return false;
+ return util::Error{_("No addresses available")};
}
{
LOCK(cs_desc_man);
@@ -1681,15 +1993,14 @@ bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDest
std::vector<CScript> scripts_temp;
if (m_wallet_descriptor.range_end <= m_max_cached_index && !TopUp(1)) {
// We can't generate anymore keys
- error = _("Error: Keypool ran out, please call keypoolrefill first");
- return false;
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
// We can't generate anymore keys
- error = _("Error: Keypool ran out, please call keypoolrefill first");
- return false;
+ return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
}
+ CTxDestination dest;
std::optional<OutputType> out_script_type = m_wallet_descriptor.descriptor->GetOutputType();
if (out_script_type && out_script_type == type) {
ExtractDestination(scripts_temp[0], dest);
@@ -1698,7 +2009,7 @@ bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDest
}
m_wallet_descriptor.next_index++;
WalletBatch(m_storage.GetDatabase()).WriteDescriptor(GetID(), m_wallet_descriptor);
- return true;
+ return dest;
}
}
@@ -1766,12 +2077,12 @@ bool DescriptorScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, Walle
return true;
}
-bool DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
+util::Result<CTxDestination> DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
{
LOCK(cs_desc_man);
- bool result = GetNewDestination(type, address, error);
+ auto op_dest = GetNewDestination(type);
index = m_wallet_descriptor.next_index - 1;
- return result;
+ return op_dest;
}
void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CTxDestination& addr)
@@ -1790,7 +2101,7 @@ std::map<CKeyID, CKey> DescriptorScriptPubKeyMan::GetKeys() const
AssertLockHeld(cs_desc_man);
if (m_storage.HasEncryptionKeys() && !m_storage.IsLocked()) {
KeyMap keys;
- for (auto key_pair : m_map_crypted_keys) {
+ for (const auto& key_pair : m_map_crypted_keys) {
const CPubKey& pubkey = key_pair.second.first;
const std::vector<unsigned char>& crypted_secret = key_pair.second.second;
CKey key;
@@ -1967,6 +2278,11 @@ bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_
desc_prefix = "tr(" + xpub + "/86'";
break;
}
+ case OutputType::UNKNOWN: {
+ // We should never have a DescriptorScriptPubKeyMan for an UNKNOWN OutputType,
+ // so if we get to this point something is wrong
+ assert(false);
+ }
} // no default case, so the compiler can warn about missing cases
assert(!desc_prefix.empty());
@@ -2076,10 +2392,21 @@ std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvid
std::unique_ptr<FlatSigningProvider> DescriptorScriptPubKeyMan::GetSigningProvider(int32_t index, bool include_private) const
{
AssertLockHeld(cs_desc_man);
- // Get the scripts, keys, and key origins for this script
+
std::unique_ptr<FlatSigningProvider> out_keys = std::make_unique<FlatSigningProvider>();
- std::vector<CScript> scripts_temp;
- if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
+
+ // Fetch SigningProvider from cache to avoid re-deriving
+ auto it = m_map_signing_providers.find(index);
+ if (it != m_map_signing_providers.end()) {
+ out_keys->Merge(FlatSigningProvider{it->second});
+ } else {
+ // Get the scripts, keys, and key origins for this script
+ std::vector<CScript> scripts_temp;
+ if (!m_wallet_descriptor.descriptor->ExpandFromCache(index, m_wallet_descriptor.cache, scripts_temp, *out_keys)) return nullptr;
+
+ // Cache SigningProvider so we don't need to re-derive if we need this SigningProvider again
+ m_map_signing_providers[index] = *out_keys;
+ }
if (HavePrivateKeys() && include_private) {
FlatSigningProvider master_provider;
@@ -2108,7 +2435,7 @@ bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const s
if (!coin_keys) {
continue;
}
- *keys = Merge(*keys, *coin_keys);
+ keys->Merge(std::move(*coin_keys));
}
return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors);
@@ -2169,15 +2496,41 @@ TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction&
std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();
std::unique_ptr<FlatSigningProvider> script_keys = GetSigningProvider(script, sign);
if (script_keys) {
- *keys = Merge(*keys, *script_keys);
+ keys->Merge(std::move(*script_keys));
} else {
// Maybe there are pubkeys listed that we can sign for
- script_keys = std::make_unique<FlatSigningProvider>();
- for (const auto& pk_pair : input.hd_keypaths) {
- const CPubKey& pubkey = pk_pair.first;
+ std::vector<CPubKey> pubkeys;
+
+ // ECDSA Pubkeys
+ for (const auto& [pk, _] : input.hd_keypaths) {
+ pubkeys.push_back(pk);
+ }
+
+ // Taproot output pubkey
+ std::vector<std::vector<unsigned char>> sols;
+ if (Solver(script, sols) == TxoutType::WITNESS_V1_TAPROOT) {
+ sols[0].insert(sols[0].begin(), 0x02);
+ pubkeys.emplace_back(sols[0]);
+ sols[0][0] = 0x03;
+ pubkeys.emplace_back(sols[0]);
+ }
+
+ // Taproot pubkeys
+ for (const auto& pk_pair : input.m_tap_bip32_paths) {
+ const XOnlyPubKey& pubkey = pk_pair.first;
+ for (unsigned char prefix : {0x02, 0x03}) {
+ unsigned char b[33] = {prefix};
+ std::copy(pubkey.begin(), pubkey.end(), b + 1);
+ CPubKey fullpubkey;
+ fullpubkey.Set(b, b + 33);
+ pubkeys.push_back(fullpubkey);
+ }
+ }
+
+ for (const auto& pubkey : pubkeys) {
std::unique_ptr<FlatSigningProvider> pk_keys = GetSigningProvider(pubkey);
if (pk_keys) {
- *keys = Merge(*keys, *pk_keys);
+ keys->Merge(std::move(*pk_keys));
}
}
}
@@ -2300,14 +2653,14 @@ const WalletDescriptor DescriptorScriptPubKeyMan::GetWalletDescriptor() const
return m_wallet_descriptor;
}
-const std::vector<CScript> DescriptorScriptPubKeyMan::GetScriptPubKeys() const
+const std::unordered_set<CScript, SaltedSipHasher> DescriptorScriptPubKeyMan::GetScriptPubKeys() const
{
LOCK(cs_desc_man);
- std::vector<CScript> script_pub_keys;
+ std::unordered_set<CScript, SaltedSipHasher> script_pub_keys;
script_pub_keys.reserve(m_map_script_pub_keys.size());
for (auto const& script_pub_key: m_map_script_pub_keys) {
- script_pub_keys.push_back(script_pub_key.first);
+ script_pub_keys.insert(script_pub_key.first);
}
return script_pub_keys;
}
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
index ad924791af..3ab489c374 100644
--- a/src/wallet/scriptpubkeyman.h
+++ b/src/wallet/scriptpubkeyman.h
@@ -11,6 +11,7 @@
#include <script/standard.h>
#include <util/error.h>
#include <util/message.h>
+#include <util/result.h>
#include <util/time.h>
#include <wallet/crypter.h>
#include <wallet/ismine.h>
@@ -171,14 +172,14 @@ protected:
public:
explicit ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
virtual ~ScriptPubKeyMan() {};
- virtual bool GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error) { return false; }
+ virtual util::Result<CTxDestination> GetNewDestination(const OutputType type) { return util::Error{Untranslated("Not supported")}; }
virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
//! Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the keys handled by it.
virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) { return false; }
virtual bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) { return false; }
- virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) { return false; }
+ virtual util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) { return util::Error{Untranslated("Not supported")}; }
virtual void KeepDestination(int64_t index, const OutputType& type) {}
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
@@ -241,6 +242,9 @@ public:
virtual uint256 GetID() const { return uint256(); }
+ /** Returns a set of all the scriptPubKeys that this ScriptPubKeyMan watches */
+ virtual const std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const { return {}; };
+
/** Prepends the wallet name in logging output to ease debugging in multi-wallet use cases */
template<typename... Params>
void WalletLogPrintf(std::string fmt, Params... parameters) const {
@@ -261,6 +265,8 @@ static const std::unordered_set<OutputType> LEGACY_OUTPUT_TYPES {
OutputType::BECH32,
};
+class DescriptorScriptPubKeyMan;
+
class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProvider
{
private:
@@ -359,13 +365,13 @@ private:
public:
using ScriptPubKeyMan::ScriptPubKeyMan;
- bool GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error) override;
+ util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
isminetype IsMine(const CScript& script) const override;
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
- bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) override;
+ util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
void KeepDestination(int64_t index, const OutputType& type) override;
void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
@@ -506,6 +512,13 @@ public:
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
std::set<CKeyID> GetKeys() const override;
+ const std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
+
+ /** Get the DescriptorScriptPubKeyMans (with private keys) that have the same scriptPubKeys as this LegacyScriptPubKeyMan.
+ * Does not modify this ScriptPubKeyMan. */
+ std::optional<MigrationData> MigrateToDescriptor();
+ /** Delete all the records ofthis LegacyScriptPubKeyMan from disk*/
+ bool DeleteRecords();
};
/** Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr. Does not provide privkeys */
@@ -546,6 +559,8 @@ private:
KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
+ // Cached FlatSigningProviders to avoid regenerating them each time they are needed.
+ mutable std::map<int32_t, FlatSigningProvider> m_map_signing_providers;
// Fetch the SigningProvider for the given script and optionally include private keys
std::unique_ptr<FlatSigningProvider> GetSigningProvider(const CScript& script, bool include_private = false) const;
// Fetch the SigningProvider for the given pubkey and always include private keys. This should only be called by signing code.
@@ -567,13 +582,13 @@ public:
mutable RecursiveMutex cs_desc_man;
- bool GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error) override;
+ util::Result<CTxDestination> GetNewDestination(const OutputType type) override;
isminetype IsMine(const CScript& script) const override;
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
- bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) override;
+ util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) override;
// Tops up the descriptor cache and m_map_script_pub_keys. The cache is stored in the wallet file
@@ -627,7 +642,7 @@ public:
void WriteDescriptor();
const WalletDescriptor GetWalletDescriptor() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
- const std::vector<CScript> GetScriptPubKeys() const;
+ const std::unordered_set<CScript, SaltedSipHasher> GetScriptPubKeys() const override;
bool GetDescriptorString(std::string& out, const bool priv) const;
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 5799a9ff2a..f534e10799 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -27,25 +27,20 @@ using interfaces::FoundBlock;
namespace wallet {
static constexpr size_t OUTPUT_GROUP_MAX_ENTRIES{100};
-int GetTxSpendSize(const CWallet& wallet, const CWalletTx& wtx, unsigned int out, bool use_max_sig)
-{
- return CalculateMaximumSignedInputSize(wtx.tx->vout[out], &wallet, use_max_sig);
-}
-
-int CalculateMaximumSignedInputSize(const CTxOut& txout, const SigningProvider* provider, bool use_max_sig)
+int CalculateMaximumSignedInputSize(const CTxOut& txout, const COutPoint outpoint, const SigningProvider* provider, const CCoinControl* coin_control)
{
CMutableTransaction txn;
- txn.vin.push_back(CTxIn(COutPoint()));
- if (!provider || !DummySignInput(*provider, txn.vin[0], txout, use_max_sig)) {
+ txn.vin.push_back(CTxIn(outpoint));
+ if (!provider || !DummySignInput(*provider, txn.vin[0], txout, coin_control)) {
return -1;
}
return GetVirtualTransactionInputSize(txn.vin[0]);
}
-int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, bool use_max_sig)
+int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet, const CCoinControl* coin_control)
{
const std::unique_ptr<SigningProvider> provider = wallet->GetSolvingProvider(txout.scriptPubKey);
- return CalculateMaximumSignedInputSize(txout, provider.get(), use_max_sig);
+ return CalculateMaximumSignedInputSize(txout, COutPoint(), provider.get(), coin_control);
}
// txouts needs to be in the order of tx.vin
@@ -84,6 +79,68 @@ TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *walle
return CalculateMaximumSignedTxSize(tx, wallet, txouts, coin_control);
}
+size_t CoinsResult::Size() const
+{
+ size_t size{0};
+ for (const auto& it : coins) {
+ size += it.second.size();
+ }
+ return size;
+}
+
+std::vector<COutput> CoinsResult::All() const
+{
+ std::vector<COutput> all;
+ all.reserve(coins.size());
+ for (const auto& it : coins) {
+ all.insert(all.end(), it.second.begin(), it.second.end());
+ }
+ return all;
+}
+
+void CoinsResult::Clear() {
+ coins.clear();
+}
+
+void CoinsResult::Erase(const std::set<COutPoint>& coins_to_remove)
+{
+ for (auto& [type, vec] : coins) {
+ auto remove_it = std::remove_if(vec.begin(), vec.end(), [&](const COutput& coin) {
+ return coins_to_remove.count(coin.outpoint) == 1;
+ });
+ vec.erase(remove_it, vec.end());
+ }
+}
+
+void CoinsResult::Shuffle(FastRandomContext& rng_fast)
+{
+ for (auto& it : coins) {
+ ::Shuffle(it.second.begin(), it.second.end(), rng_fast);
+ }
+}
+
+void CoinsResult::Add(OutputType type, const COutput& out)
+{
+ coins[type].emplace_back(out);
+}
+
+static OutputType GetOutputType(TxoutType type, bool is_from_p2sh)
+{
+ switch (type) {
+ case TxoutType::WITNESS_V1_TAPROOT:
+ return OutputType::BECH32M;
+ case TxoutType::WITNESS_V0_KEYHASH:
+ case TxoutType::WITNESS_V0_SCRIPTHASH:
+ if (is_from_p2sh) return OutputType::P2SH_SEGWIT;
+ else return OutputType::BECH32;
+ case TxoutType::SCRIPTHASH:
+ case TxoutType::PUBKEYHASH:
+ return OutputType::LEGACY;
+ default:
+ return OutputType::UNKNOWN;
+ }
+}
+
CoinsResult AvailableCoins(const CWallet& wallet,
const CCoinControl* coinControl,
std::optional<CFeeRate> feerate,
@@ -192,16 +249,44 @@ CoinsResult AvailableCoins(const CWallet& wallet,
std::unique_ptr<SigningProvider> provider = wallet.GetSolvingProvider(output.scriptPubKey);
- bool solvable = provider ? IsSolvable(*provider, output.scriptPubKey) : false;
+ int input_bytes = CalculateMaximumSignedInputSize(output, COutPoint(), provider.get(), coinControl);
+ // Because CalculateMaximumSignedInputSize just uses ProduceSignature and makes a dummy signature,
+ // it is safe to assume that this input is solvable if input_bytes is greater -1.
+ bool solvable = input_bytes > -1;
bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
// Filter by spendable outputs only
if (!spendable && only_spendable) continue;
- int input_bytes = GetTxSpendSize(wallet, wtx, i, (coinControl && coinControl->fAllowWatchOnly));
- result.coins.emplace_back(outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me, feerate);
- result.total_amount += output.nValue;
+ // If the Output is P2SH and spendable, we want to know if it is
+ // a P2SH (legacy) or one of P2SH-P2WPKH, P2SH-P2WSH (P2SH-Segwit). We can determine
+ // this from the redeemScript. If the Output is not spendable, it will be classified
+ // as a P2SH (legacy), since we have no way of knowing otherwise without the redeemScript
+ CScript script;
+ bool is_from_p2sh{false};
+ if (output.scriptPubKey.IsPayToScriptHash() && solvable) {
+ CTxDestination destination;
+ if (!ExtractDestination(output.scriptPubKey, destination))
+ continue;
+ const CScriptID& hash = CScriptID(std::get<ScriptHash>(destination));
+ if (!provider->GetCScript(hash, script))
+ continue;
+ is_from_p2sh = true;
+ } else {
+ script = output.scriptPubKey;
+ }
+
+ COutput coin(outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime(), tx_from_me, feerate);
+
+ // When parsing a scriptPubKey, Solver returns the parsed pubkeys or hashes (depending on the script)
+ // We don't need those here, so we are leaving them in return_values_unused
+ std::vector<std::vector<uint8_t>> return_values_unused;
+ TxoutType type;
+ type = Solver(script, return_values_unused);
+ result.Add(GetOutputType(type, is_from_p2sh), coin);
+ // Cache total amount as we go
+ result.total_amount += output.nValue;
// Checks the sum amount of all UTXO's.
if (nMinimumSumAmount != MAX_MONEY) {
if (result.total_amount >= nMinimumSumAmount) {
@@ -210,7 +295,7 @@ CoinsResult AvailableCoins(const CWallet& wallet,
}
// Checks the maximum number of UTXO's.
- if (nMaximumCount > 0 && result.coins.size() >= nMaximumCount) {
+ if (nMaximumCount > 0 && result.Size() >= nMaximumCount) {
return result;
}
}
@@ -266,7 +351,7 @@ std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet)
std::map<CTxDestination, std::vector<COutput>> result;
- for (const COutput& coin : AvailableCoinsListUnspent(wallet).coins) {
+ for (COutput& coin : AvailableCoinsListUnspent(wallet).All()) {
CTxDestination address;
if ((coin.spendable || (wallet.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && coin.solvable)) &&
ExtractDestination(FindNonChangeParentOutput(wallet, coin.outpoint).scriptPubKey, address)) {
@@ -289,8 +374,9 @@ std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet)
) {
CTxDestination address;
if (ExtractDestination(FindNonChangeParentOutput(wallet, *wtx.tx, output.n).scriptPubKey, address)) {
+ const auto out = wtx.tx->vout.at(output.n);
result[address].emplace_back(
- COutPoint(wtx.GetHash(), output.n), wtx.tx->vout.at(output.n), depth, GetTxSpendSize(wallet, wtx, output.n), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ false, wtx.GetTxTime(), CachedTxIsFromMe(wallet, wtx, ISMINE_ALL));
+ COutPoint(wtx.GetHash(), output.n), out, depth, CalculateMaximumSignedInputSize(out, &wallet, /*coin_control=*/nullptr), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ false, wtx.GetTxTime(), CachedTxIsFromMe(wallet, wtx, ISMINE_ALL));
}
}
}
@@ -383,35 +469,51 @@ std::vector<OutputGroup> GroupOutputs(const CWallet& wallet, const std::vector<C
return groups_out;
}
-std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutput> coins,
- const CoinSelectionParams& coin_selection_params)
+std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const CoinsResult& available_coins,
+ const CoinSelectionParams& coin_selection_params, bool allow_mixed_output_types)
+{
+ // Run coin selection on each OutputType and compute the Waste Metric
+ std::vector<SelectionResult> results;
+ for (const auto& it : available_coins.coins) {
+ if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, it.second, coin_selection_params)}) {
+ results.push_back(*result);
+ }
+ }
+ // If we have at least one solution for funding the transaction without mixing, choose the minimum one according to waste metric
+ // and return the result
+ if (results.size() > 0) return *std::min_element(results.begin(), results.end());
+
+ // If we can't fund the transaction from any individual OutputType, run coin selection one last time
+ // over all available coins, which would allow mixing
+ if (allow_mixed_output_types) {
+ if (auto result{ChooseSelectionResult(wallet, nTargetValue, eligibility_filter, available_coins.All(), coin_selection_params)}) {
+ return result;
+ }
+ }
+ // Either mixing is not allowed and we couldn't find a solution from any single OutputType, or mixing was allowed and we still couldn't
+ // find a solution using all available coins
+ return std::nullopt;
+};
+
+std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const std::vector<COutput>& available_coins, const CoinSelectionParams& coin_selection_params)
{
// Vector of results. We will choose the best one based on waste.
std::vector<SelectionResult> results;
- // Note that unlike KnapsackSolver, we do not include the fee for creating a change output as BnB will not create a change output.
- std::vector<OutputGroup> positive_groups = GroupOutputs(wallet, coins, coin_selection_params, eligibility_filter, true /* positive_only */);
+ std::vector<OutputGroup> positive_groups = GroupOutputs(wallet, available_coins, coin_selection_params, eligibility_filter, /*positive_only=*/true);
if (auto bnb_result{SelectCoinsBnB(positive_groups, nTargetValue, coin_selection_params.m_cost_of_change)}) {
results.push_back(*bnb_result);
}
// The knapsack solver has some legacy behavior where it will spend dust outputs. We retain this behavior, so don't filter for positive only here.
- std::vector<OutputGroup> all_groups = GroupOutputs(wallet, coins, coin_selection_params, eligibility_filter, false /* positive_only */);
- // While nTargetValue includes the transaction fees for non-input things, it does not include the fee for creating a change output.
- // So we need to include that for KnapsackSolver as well, as we are expecting to create a change output.
- if (auto knapsack_result{KnapsackSolver(all_groups, nTargetValue + coin_selection_params.m_change_fee,
- coin_selection_params.m_min_change_target, coin_selection_params.rng_fast)}) {
- knapsack_result->ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
+ std::vector<OutputGroup> all_groups = GroupOutputs(wallet, available_coins, coin_selection_params, eligibility_filter, /*positive_only=*/false);
+ if (auto knapsack_result{KnapsackSolver(all_groups, nTargetValue, coin_selection_params.m_min_change_target, coin_selection_params.rng_fast)}) {
+ knapsack_result->ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee);
results.push_back(*knapsack_result);
}
- // Include change for SRD as we want to avoid making really small change if the selection just
- // barely meets the target. Just use the lower bound change target instead of the randomly
- // generated one, since SRD will result in a random change amount anyway; avoid making the
- // target needlessly large.
- const CAmount srd_target = nTargetValue + coin_selection_params.m_change_fee + CHANGE_LOWER;
- if (auto srd_result{SelectCoinsSRD(positive_groups, srd_target, coin_selection_params.rng_fast)}) {
- srd_result->ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
+ if (auto srd_result{SelectCoinsSRD(positive_groups, nTargetValue, coin_selection_params.rng_fast)}) {
+ srd_result->ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee);
results.push_back(*srd_result);
}
@@ -426,9 +528,8 @@ std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAm
return best_result;
}
-std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
+std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
{
- std::vector<COutput> vCoins(vAvailableCoins);
CAmount value_to_select = nTargetValue;
OutputGroup preset_inputs(coin_selection_params);
@@ -447,15 +548,19 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
if (ptr_wtx->tx->vout.size() <= outpoint.n) {
return std::nullopt;
}
- input_bytes = GetTxSpendSize(wallet, *ptr_wtx, outpoint.n, false);
txout = ptr_wtx->tx->vout.at(outpoint.n);
+ input_bytes = CalculateMaximumSignedInputSize(txout, &wallet, &coin_control);
} else {
// The input is external. We did not find the tx in mapWallet.
if (!coin_control.GetExternalOutput(outpoint, txout)) {
return std::nullopt;
}
- input_bytes = CalculateMaximumSignedInputSize(txout, &coin_control.m_external_provider, /*use_max_sig=*/true);
}
+
+ if (input_bytes == -1) {
+ input_bytes = CalculateMaximumSignedInputSize(txout, outpoint, &coin_control.m_external_provider, &coin_control);
+ }
+
// If available, override calculated size with coin control specified size
if (coin_control.HasInputWeight(outpoint)) {
input_bytes = GetVirtualTransactionSize(coin_control.GetInputWeight(outpoint), 0, 0);
@@ -483,18 +588,20 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
if (coin_control.HasSelected() && !coin_control.m_allow_other_inputs) {
SelectionResult result(nTargetValue, SelectionAlgorithm::MANUAL);
result.AddInput(preset_inputs);
- if (result.GetSelectedValue() < nTargetValue) return std::nullopt;
- result.ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
+
+ if (!coin_selection_params.m_subtract_fee_outputs && result.GetSelectedEffectiveValue() < nTargetValue) {
+ return std::nullopt;
+ } else if (result.GetSelectedValue() < nTargetValue) {
+ return std::nullopt;
+ }
+
+ result.ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee);
return result;
}
- // remove preset inputs from vCoins so that Coin Selection doesn't pick them.
- for (std::vector<COutput>::iterator it = vCoins.begin(); it != vCoins.end() && coin_control.HasSelected();)
- {
- if (preset_coins.count(it->outpoint))
- it = vCoins.erase(it);
- else
- ++it;
+ // remove preset inputs from coins so that Coin Selection doesn't pick them.
+ if (coin_control.HasSelected()) {
+ available_coins.Erase(preset_coins);
}
unsigned int limit_ancestor_count = 0;
@@ -506,42 +613,46 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
// form groups from remaining coins; note that preset coins will not
// automatically have their associated (same address) coins included
- if (coin_control.m_avoid_partial_spends && vCoins.size() > OUTPUT_GROUP_MAX_ENTRIES) {
+ if (coin_control.m_avoid_partial_spends && available_coins.Size() > OUTPUT_GROUP_MAX_ENTRIES) {
// Cases where we have 101+ outputs all pointing to the same destination may result in
// privacy leaks as they will potentially be deterministically sorted. We solve that by
// explicitly shuffling the outputs before processing
- Shuffle(vCoins.begin(), vCoins.end(), coin_selection_params.rng_fast);
+ available_coins.Shuffle(coin_selection_params.rng_fast);
}
+ SelectionResult preselected(preset_inputs.GetSelectionAmount(), SelectionAlgorithm::MANUAL);
+ preselected.AddInput(preset_inputs);
+
// Coin Selection attempts to select inputs from a pool of eligible UTXOs to fund the
// transaction at a target feerate. If an attempt fails, more attempts may be made using a more
// permissive CoinEligibilityFilter.
std::optional<SelectionResult> res = [&] {
// Pre-selected inputs already cover the target amount.
- if (value_to_select <= 0) return std::make_optional(SelectionResult(nTargetValue, SelectionAlgorithm::MANUAL));
+ if (value_to_select <= 0) return std::make_optional(SelectionResult(value_to_select, SelectionAlgorithm::MANUAL));
// If possible, fund the transaction with confirmed UTXOs only. Prefer at least six
// confirmations on outputs received from other wallets and only spend confirmed change.
- if (auto r1{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 6, 0), vCoins, coin_selection_params)}) return r1;
- if (auto r2{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 1, 0), vCoins, coin_selection_params)}) return r2;
+ if (auto r1{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 6, 0), available_coins, coin_selection_params, /*allow_mixed_output_types=*/false)}) return r1;
+ // Allow mixing only if no solution from any single output type can be found
+ if (auto r2{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 1, 0), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) return r2;
// Fall back to using zero confirmation change (but with as few ancestors in the mempool as
// possible) if we cannot fund the transaction otherwise.
if (wallet.m_spend_zero_conf_change) {
- if (auto r3{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, coin_selection_params)}) return r3;
+ if (auto r3{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, 2), available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) return r3;
if (auto r4{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r4;
}
if (auto r5{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r5;
}
// If partial groups are allowed, relax the requirement of spending OutputGroups (groups
// of UTXOs sent to the same address, which are obviously controlled by a single wallet)
// in their entirety.
if (auto r6{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r6;
}
// Try with unsafe inputs if they are allowed. This may spend unconfirmed outputs
@@ -549,7 +660,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
if (coin_control.m_include_unsafe_inputs) {
if (auto r7{AttemptSelection(wallet, value_to_select,
CoinEligibilityFilter(0 /* conf_mine */, 0 /* conf_theirs */, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r7;
}
}
@@ -559,7 +670,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
if (!fRejectLongChains) {
if (auto r8{AttemptSelection(wallet, value_to_select,
CoinEligibilityFilter(0, 1, std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max(), true /* include_partial_groups */),
- vCoins, coin_selection_params)}) {
+ available_coins, coin_selection_params, /*allow_mixed_output_types=*/true)}) {
return r8;
}
}
@@ -571,9 +682,9 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
if (!res) return std::nullopt;
// Add preset inputs to result
- res->AddInput(preset_inputs);
- if (res->m_algo == SelectionAlgorithm::MANUAL) {
- res->ComputeAndSetWaste(coin_selection_params.m_cost_of_change);
+ res->Merge(preselected);
+ if (res->GetAlgo() == SelectionAlgorithm::MANUAL) {
+ res->ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee);
}
return res;
@@ -653,19 +764,16 @@ static void DiscourageFeeSniping(CMutableTransaction& tx, FastRandomContext& rng
}
}
-static std::optional<CreatedTransactionResult> CreateTransactionInternal(
+static util::Result<CreatedTransactionResult> CreateTransactionInternal(
CWallet& wallet,
const std::vector<CRecipient>& vecSend,
int change_pos,
- bilingual_str& error,
const CCoinControl& coin_control,
- FeeCalculation& fee_calc_out,
bool sign) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
AssertLockHeld(wallet.cs_wallet);
// out variables, to be packed into returned result structure
- CTransactionRef tx;
CAmount nFeeRet;
int nChangePosInOut = change_pos;
@@ -690,10 +798,10 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
coin_selection_params.m_subtract_fee_outputs = true;
}
}
- coin_selection_params.m_change_target = GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), rng_fast);
// Create change script that will be used if we need change
CScript scriptChange;
+ bilingual_str error; // possible error str
// coin control: send change to custom address
if (!std::get_if<CNoDestination>(&coin_control.destChange)) {
@@ -709,11 +817,13 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
// Reserve a new key pair from key pool. If it fails, provide a dummy
// destination in case we don't need change.
CTxDestination dest;
- bilingual_str dest_err;
- if (!reservedest.GetReservedDestination(dest, true, dest_err)) {
- error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + dest_err;
+ auto op_dest = reservedest.GetReservedDestination(true);
+ if (!op_dest) {
+ error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + util::ErrorString(op_dest);
+ } else {
+ dest = *op_dest;
+ scriptChange = GetScriptForDestination(dest);
}
- scriptChange = GetScriptForDestination(dest);
// A valid destination implies a change script (and
// vice-versa). An empty change script will abort later, if the
// change keypool ran out, but change is required.
@@ -741,13 +851,11 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
// Do not, ever, assume that it's fine to change the fee rate if the user has explicitly
// provided one
if (coin_control.m_feerate && coin_selection_params.m_effective_feerate > *coin_control.m_feerate) {
- error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), coin_selection_params.m_effective_feerate.ToString(FeeEstimateMode::SAT_VB));
- return std::nullopt;
+ return util::Error{strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), coin_selection_params.m_effective_feerate.ToString(FeeEstimateMode::SAT_VB))};
}
if (feeCalc.reason == FeeReason::FALLBACK && !wallet.m_allow_fallback_fee) {
// eventually allow a fallback fee
- error = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
- return std::nullopt;
+ return util::Error{_("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.")};
}
// Calculate the cost of change
@@ -758,9 +866,19 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
coin_selection_params.m_cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + coin_selection_params.m_change_fee;
+ coin_selection_params.m_min_change_target = GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), coin_selection_params.m_change_fee, rng_fast);
+
+ // The smallest change amount should be:
+ // 1. at least equal to dust threshold
+ // 2. at least 1 sat greater than fees to spend it at m_discard_feerate
+ const auto dust = GetDustThreshold(change_prototype_txout, coin_selection_params.m_discard_feerate);
+ const auto change_spend_fee = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size);
+ coin_selection_params.min_viable_change = std::max(change_spend_fee + 1, dust);
+
// vouts to the payees
if (!coin_selection_params.m_subtract_fee_outputs) {
- coin_selection_params.tx_noinputs_size = 11; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size)
+ coin_selection_params.tx_noinputs_size = 10; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size)
+ coin_selection_params.tx_noinputs_size += GetSizeOfCompactSize(vecSend.size()); // bytes for output count
}
for (const auto& recipient : vecSend)
{
@@ -771,10 +889,8 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
coin_selection_params.tx_noinputs_size += ::GetSerializeSize(txout, PROTOCOL_VERSION);
}
- if (IsDust(txout, wallet.chain().relayDustFee()))
- {
- error = _("Transaction amount too small");
- return std::nullopt;
+ if (IsDust(txout, wallet.chain().relayDustFee())) {
+ return util::Error{_("Transaction amount too small")};
}
txNew.vout.push_back(txout);
}
@@ -784,7 +900,7 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
CAmount selection_target = recipients_sum + not_input_fees;
// Get available coins
- auto res_available_coins = AvailableCoins(wallet,
+ auto available_coins = AvailableCoins(wallet,
&coin_control,
coin_selection_params.m_effective_feerate,
1, /*nMinimumAmount*/
@@ -793,32 +909,26 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
0); /*nMaximumCount*/
// Choose coins to use
- std::optional<SelectionResult> result = SelectCoins(wallet, res_available_coins.coins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
+ std::optional<SelectionResult> result = SelectCoins(wallet, available_coins, /*nTargetValue=*/selection_target, coin_control, coin_selection_params);
if (!result) {
- error = _("Insufficient funds");
- return std::nullopt;
- }
- TRACE5(coin_selection, selected_coins, wallet.GetName().c_str(), GetAlgorithmName(result->m_algo).c_str(), result->m_target, result->GetWaste(), result->GetSelectedValue());
-
- // Always make a change output
- // We will reduce the fee from this change output later, and remove the output if it is too small.
- const CAmount change_and_fee = result->GetSelectedValue() - recipients_sum;
- assert(change_and_fee >= 0);
- CTxOut newTxOut(change_and_fee, scriptChange);
-
- if (nChangePosInOut == -1) {
- // Insert change txn at random position:
- nChangePosInOut = rng_fast.randrange(txNew.vout.size() + 1);
+ return util::Error{_("Insufficient funds")};
}
- else if ((unsigned int)nChangePosInOut > txNew.vout.size())
- {
- error = _("Transaction change output index out of range");
- return std::nullopt;
+ TRACE5(coin_selection, selected_coins, wallet.GetName().c_str(), GetAlgorithmName(result->GetAlgo()).c_str(), result->GetTarget(), result->GetWaste(), result->GetSelectedValue());
+
+ const CAmount change_amount = result->GetChange(coin_selection_params.min_viable_change, coin_selection_params.m_change_fee);
+ if (change_amount > 0) {
+ CTxOut newTxOut(change_amount, scriptChange);
+ if (nChangePosInOut == -1) {
+ // Insert change txn at random position:
+ nChangePosInOut = rng_fast.randrange(txNew.vout.size() + 1);
+ } else if ((unsigned int)nChangePosInOut > txNew.vout.size()) {
+ return util::Error{_("Transaction change output index out of range")};
+ }
+ txNew.vout.insert(txNew.vout.begin() + nChangePosInOut, newTxOut);
+ } else {
+ nChangePosInOut = -1;
}
- assert(nChangePosInOut != -1);
- auto change_position = txNew.vout.insert(txNew.vout.begin() + nChangePosInOut, newTxOut);
-
// Shuffle selected coins and fill in final vin
std::vector<COutput> selected_coins = result->GetShuffledInputVector();
@@ -840,45 +950,25 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
TxSize tx_sizes = CalculateMaximumSignedTxSize(CTransaction(txNew), &wallet, &coin_control);
int nBytes = tx_sizes.vsize;
if (nBytes == -1) {
- error = _("Missing solving data for estimating transaction size");
- return std::nullopt;
+ return util::Error{_("Missing solving data for estimating transaction size")};
}
- nFeeRet = coin_selection_params.m_effective_feerate.GetFee(nBytes);
+ CAmount fee_needed = coin_selection_params.m_effective_feerate.GetFee(nBytes);
+ nFeeRet = result->GetSelectedValue() - recipients_sum - change_amount;
- // Subtract fee from the change output if not subtracting it from recipient outputs
- CAmount fee_needed = nFeeRet;
- if (!coin_selection_params.m_subtract_fee_outputs) {
- change_position->nValue -= fee_needed;
- }
-
- // We want to drop the change to fees if:
- // 1. The change output would be dust
- // 2. The change is within the (almost) exact match window, i.e. it is less than or equal to the cost of the change output (cost_of_change)
- CAmount change_amount = change_position->nValue;
- if (IsDust(*change_position, coin_selection_params.m_discard_feerate) || change_amount <= coin_selection_params.m_cost_of_change)
- {
- nChangePosInOut = -1;
- change_amount = 0;
- txNew.vout.erase(change_position);
-
- // Because we have dropped this change, the tx size and required fee will be different, so let's recalculate those
- tx_sizes = CalculateMaximumSignedTxSize(CTransaction(txNew), &wallet, &coin_control);
- nBytes = tx_sizes.vsize;
- fee_needed = coin_selection_params.m_effective_feerate.GetFee(nBytes);
- }
-
- // The only time that fee_needed should be less than the amount available for fees (in change_and_fee - change_amount) is when
+ // The only time that fee_needed should be less than the amount available for fees is when
// we are subtracting the fee from the outputs. If this occurs at any other time, it is a bug.
- assert(coin_selection_params.m_subtract_fee_outputs || fee_needed <= change_and_fee - change_amount);
+ assert(coin_selection_params.m_subtract_fee_outputs || fee_needed <= nFeeRet);
- // Update nFeeRet in case fee_needed changed due to dropping the change output
- if (fee_needed <= change_and_fee - change_amount) {
- nFeeRet = change_and_fee - change_amount;
+ // If there is a change output and we overpay the fees then increase the change to match the fee needed
+ if (nChangePosInOut != -1 && fee_needed < nFeeRet) {
+ auto& change = txNew.vout.at(nChangePosInOut);
+ change.nValue += nFeeRet - fee_needed;
+ nFeeRet = fee_needed;
}
// Reduce output values for subtractFeeFromAmount
if (coin_selection_params.m_subtract_fee_outputs) {
- CAmount to_reduce = fee_needed + change_amount - change_and_fee;
+ CAmount to_reduce = fee_needed - nFeeRet;
int i = 0;
bool fFirst = true;
for (const auto& recipient : vecSend)
@@ -901,11 +991,10 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
// Error if this output is reduced to be below dust
if (IsDust(txout, wallet.chain().relayDustFee())) {
if (txout.nValue < 0) {
- error = _("The transaction amount is too small to pay the fee");
+ return util::Error{_("The transaction amount is too small to pay the fee")};
} else {
- error = _("The transaction amount is too small to send after the fee has been deducted");
+ return util::Error{_("The transaction amount is too small to send after the fee has been deducted")};
}
- return std::nullopt;
}
}
++i;
@@ -915,42 +1004,37 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
// Give up if change keypool ran out and change is required
if (scriptChange.empty() && nChangePosInOut != -1) {
- return std::nullopt;
+ return util::Error{error};
}
if (sign && !wallet.SignTransaction(txNew)) {
- error = _("Signing transaction failed");
- return std::nullopt;
+ return util::Error{_("Signing transaction failed")};
}
// Return the constructed transaction data.
- tx = MakeTransactionRef(std::move(txNew));
+ CTransactionRef tx = MakeTransactionRef(std::move(txNew));
// Limit size
if ((sign && GetTransactionWeight(*tx) > MAX_STANDARD_TX_WEIGHT) ||
(!sign && tx_sizes.weight > MAX_STANDARD_TX_WEIGHT))
{
- error = _("Transaction too large");
- return std::nullopt;
+ return util::Error{_("Transaction too large")};
}
if (nFeeRet > wallet.m_default_max_tx_fee) {
- error = TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED);
- return std::nullopt;
+ return util::Error{TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED)};
}
if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) {
// Lastly, ensure this tx will pass the mempool's chain limits
if (!wallet.chain().checkChainLimits(tx)) {
- error = _("Transaction has too long of a mempool chain");
- return std::nullopt;
+ return util::Error{_("Transaction has too long of a mempool chain")};
}
}
// Before we return success, we assume any change key will be used to prevent
// accidental re-use.
reservedest.KeepDestination();
- fee_calc_out = feeCalc;
wallet.WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n",
nFeeRet, nBytes, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
@@ -960,52 +1044,48 @@ static std::optional<CreatedTransactionResult> CreateTransactionInternal(
feeCalc.est.fail.start, feeCalc.est.fail.end,
(feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) > 0.0 ? 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool) : 0.0,
feeCalc.est.fail.withinTarget, feeCalc.est.fail.totalConfirmed, feeCalc.est.fail.inMempool, feeCalc.est.fail.leftMempool);
- return CreatedTransactionResult(tx, nFeeRet, nChangePosInOut);
+ return CreatedTransactionResult(tx, nFeeRet, nChangePosInOut, feeCalc);
}
-std::optional<CreatedTransactionResult> CreateTransaction(
+util::Result<CreatedTransactionResult> CreateTransaction(
CWallet& wallet,
const std::vector<CRecipient>& vecSend,
int change_pos,
- bilingual_str& error,
const CCoinControl& coin_control,
- FeeCalculation& fee_calc_out,
bool sign)
{
if (vecSend.empty()) {
- error = _("Transaction must have at least one recipient");
- return std::nullopt;
+ return util::Error{_("Transaction must have at least one recipient")};
}
if (std::any_of(vecSend.cbegin(), vecSend.cend(), [](const auto& recipient){ return recipient.nAmount < 0; })) {
- error = _("Transaction amounts must not be negative");
- return std::nullopt;
+ return util::Error{_("Transaction amounts must not be negative")};
}
LOCK(wallet.cs_wallet);
- std::optional<CreatedTransactionResult> txr_ungrouped = CreateTransactionInternal(wallet, vecSend, change_pos, error, coin_control, fee_calc_out, sign);
- TRACE4(coin_selection, normal_create_tx_internal, wallet.GetName().c_str(), txr_ungrouped.has_value(),
- txr_ungrouped.has_value() ? txr_ungrouped->fee : 0, txr_ungrouped.has_value() ? txr_ungrouped->change_pos : 0);
- if (!txr_ungrouped) return std::nullopt;
+ auto res = CreateTransactionInternal(wallet, vecSend, change_pos, coin_control, sign);
+ TRACE4(coin_selection, normal_create_tx_internal, wallet.GetName().c_str(), bool(res),
+ res ? res->fee : 0, res ? res->change_pos : 0);
+ if (!res) return res;
+ const auto& txr_ungrouped = *res;
// try with avoidpartialspends unless it's enabled already
- if (txr_ungrouped->fee > 0 /* 0 means non-functional fee rate estimation */ && wallet.m_max_aps_fee > -1 && !coin_control.m_avoid_partial_spends) {
+ if (txr_ungrouped.fee > 0 /* 0 means non-functional fee rate estimation */ && wallet.m_max_aps_fee > -1 && !coin_control.m_avoid_partial_spends) {
TRACE1(coin_selection, attempting_aps_create_tx, wallet.GetName().c_str());
CCoinControl tmp_cc = coin_control;
tmp_cc.m_avoid_partial_spends = true;
- bilingual_str error2; // fired and forgotten; if an error occurs, we discard the results
- std::optional<CreatedTransactionResult> txr_grouped = CreateTransactionInternal(wallet, vecSend, change_pos, error2, tmp_cc, fee_calc_out, sign);
+ auto txr_grouped = CreateTransactionInternal(wallet, vecSend, change_pos, tmp_cc, sign);
// if fee of this alternative one is within the range of the max fee, we use this one
- const bool use_aps{txr_grouped.has_value() ? (txr_grouped->fee <= txr_ungrouped->fee + wallet.m_max_aps_fee) : false};
+ const bool use_aps{txr_grouped.has_value() ? (txr_grouped->fee <= txr_ungrouped.fee + wallet.m_max_aps_fee) : false};
TRACE5(coin_selection, aps_create_tx_internal, wallet.GetName().c_str(), use_aps, txr_grouped.has_value(),
txr_grouped.has_value() ? txr_grouped->fee : 0, txr_grouped.has_value() ? txr_grouped->change_pos : 0);
if (txr_grouped) {
wallet.WalletLogPrintf("Fee non-grouped = %lld, grouped = %lld, using %s\n",
- txr_ungrouped->fee, txr_grouped->fee, use_aps ? "grouped" : "non-grouped");
+ txr_ungrouped.fee, txr_grouped->fee, use_aps ? "grouped" : "non-grouped");
if (use_aps) return txr_grouped;
}
}
- return txr_ungrouped;
+ return res;
}
bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
@@ -1032,21 +1112,28 @@ bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet,
wallet.chain().findCoins(coins);
for (const CTxIn& txin : tx.vin) {
- // if it's not in the wallet and corresponding UTXO is found than select as external output
const auto& outPoint = txin.prevout;
- if (wallet.mapWallet.find(outPoint.hash) == wallet.mapWallet.end() && !coins[outPoint].out.IsNull()) {
- coinControl.SelectExternal(outPoint, coins[outPoint].out);
- } else {
+ if (wallet.IsMine(outPoint)) {
+ // The input was found in the wallet, so select as internal
coinControl.Select(outPoint);
+ } else if (coins[outPoint].out.IsNull()) {
+ error = _("Unable to find UTXO for external input");
+ return false;
+ } else {
+ // The input was not in the wallet, but is in the UTXO set, so select as external
+ coinControl.SelectExternal(outPoint, coins[outPoint].out);
}
}
- FeeCalculation fee_calc_out;
- std::optional<CreatedTransactionResult> txr = CreateTransaction(wallet, vecSend, nChangePosInOut, error, coinControl, fee_calc_out, false);
- if (!txr) return false;
- CTransactionRef tx_new = txr->tx;
- nFeeRet = txr->fee;
- nChangePosInOut = txr->change_pos;
+ auto res = CreateTransaction(wallet, vecSend, nChangePosInOut, coinControl, false);
+ if (!res) {
+ error = util::ErrorString(res);
+ return false;
+ }
+ const auto& txr = *res;
+ CTransactionRef tx_new = txr.tx;
+ nFeeRet = txr.fee;
+ nChangePosInOut = txr.change_pos;
if (nChangePosInOut != -1) {
tx.vout.insert(tx.vout.begin() + nChangePosInOut, tx_new->vout[nChangePosInOut]);
diff --git a/src/wallet/spend.h b/src/wallet/spend.h
index cba42d6fae..009e680627 100644
--- a/src/wallet/spend.h
+++ b/src/wallet/spend.h
@@ -6,6 +6,8 @@
#define BITCOIN_WALLET_SPEND_H
#include <consensus/amount.h>
+#include <policy/fees.h> // for FeeCalculation
+#include <util/result.h>
#include <wallet/coinselection.h>
#include <wallet/transaction.h>
#include <wallet/wallet.h>
@@ -14,34 +16,47 @@
namespace wallet {
/** Get the marginal bytes if spending the specified output from this transaction.
- * use_max_sig indicates whether to use the maximum sized, 72 byte signature when calculating the
- * size of the input spend. This should only be set when watch-only outputs are allowed */
-int GetTxSpendSize(const CWallet& wallet, const CWalletTx& wtx, unsigned int out, bool use_max_sig = false);
-
-//Get the marginal bytes of spending the specified output
-int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, bool use_max_sig = false);
-int CalculateMaximumSignedInputSize(const CTxOut& txout, const SigningProvider* pwallet, bool use_max_sig = false);
-
+ * Use CoinControl to determine whether to expect signature grinding when calculating the size of the input spend. */
+int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* pwallet, const CCoinControl* coin_control = nullptr);
+int CalculateMaximumSignedInputSize(const CTxOut& txout, const COutPoint outpoint, const SigningProvider* pwallet, const CCoinControl* coin_control = nullptr);
struct TxSize {
int64_t vsize{-1};
int64_t weight{-1};
};
-/** Calculate the size of the transaction assuming all signatures are max size
-* Use DummySignatureCreator, which inserts 71 byte signatures everywhere.
-* NOTE: this requires that all inputs must be in mapWallet (eg the tx should
-* be AllInputsMine). */
+/** Calculate the size of the transaction using CoinControl to determine
+ * whether to expect signature grinding when calculating the size of the input spend. */
TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control = nullptr);
TxSize CalculateMaximumSignedTxSize(const CTransaction& tx, const CWallet* wallet, const CCoinControl* coin_control = nullptr) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
+/**
+ * COutputs available for spending, stored by OutputType.
+ * This struct is really just a wrapper around OutputType vectors with a convenient
+ * method for concatenating and returning all COutputs as one vector.
+ *
+ * Size(), Clear(), Erase(), Shuffle(), and Add() methods are implemented to
+ * allow easy interaction with the struct.
+ */
struct CoinsResult {
- std::vector<COutput> coins;
- // Sum of all the coins amounts
+ std::map<OutputType, std::vector<COutput>> coins;
+
+ /** Concatenate and return all COutputs as one vector */
+ std::vector<COutput> All() const;
+
+ /** The following methods are provided so that CoinsResult can mimic a vector,
+ * i.e., methods can work with individual OutputType vectors or on the entire object */
+ size_t Size() const;
+ void Clear();
+ void Erase(const std::set<COutPoint>& coins_to_remove);
+ void Shuffle(FastRandomContext& rng_fast);
+ void Add(OutputType type, const COutput& out);
+
+ /** Sum of all available coins */
CAmount total_amount{0};
};
+
/**
- * Return vector of available COutputs.
- * By default, returns only the spendable coins.
+ * Populate the CoinsResult struct with vectors of available COutputs, organized by OutputType.
*/
CoinsResult AvailableCoins(const CWallet& wallet,
const CCoinControl* coinControl = nullptr,
@@ -72,45 +87,63 @@ const CTxOut& FindNonChangeParentOutput(const CWallet& wallet, const COutPoint&
std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
std::vector<OutputGroup> GroupOutputs(const CWallet& wallet, const std::vector<COutput>& outputs, const CoinSelectionParams& coin_sel_params, const CoinEligibilityFilter& filter, bool positive_only);
+/**
+ * Attempt to find a valid input set that preserves privacy by not mixing OutputTypes.
+ * `ChooseSelectionResult()` will be called on each OutputType individually and the best
+ * the solution (according to the waste metric) will be chosen. If a valid input cannot be found from any
+ * single OutputType, fallback to running `ChooseSelectionResult()` over all available coins.
+ *
+ * param@[in] wallet The wallet which provides solving data for the coins
+ * param@[in] nTargetValue The target value
+ * param@[in] eligilibity_filter A filter containing rules for which coins are allowed to be included in this selection
+ * param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
+ * param@[in] coin_selection_params Parameters for the coin selection
+ * param@[in] allow_mixed_output_types Relax restriction that SelectionResults must be of the same OutputType
+ * returns If successful, a SelectionResult containing the input set
+ * If failed, a nullopt
+ */
+std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const CoinsResult& available_coins,
+ const CoinSelectionParams& coin_selection_params, bool allow_mixed_output_types);
/**
* Attempt to find a valid input set that meets the provided eligibility filter and target.
* Multiple coin selection algorithms will be run and the input set that produces the least waste
* (according to the waste metric) will be chosen.
*
- * param@[in] wallet The wallet which provides solving data for the coins
- * param@[in] nTargetValue The target value
- * param@[in] eligilibity_filter A filter containing rules for which coins are allowed to be included in this selection
- * param@[in] coins The vector of coins available for selection prior to filtering
- * param@[in] coin_selection_params Parameters for the coin selection
- * returns If successful, a SelectionResult containing the input set
- * If failed, a nullopt
+ * param@[in] wallet The wallet which provides solving data for the coins
+ * param@[in] nTargetValue The target value
+ * param@[in] eligilibity_filter A filter containing rules for which coins are allowed to be included in this selection
+ * param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
+ * param@[in] coin_selection_params Parameters for the coin selection
+ * returns If successful, a SelectionResult containing the input set
+ * If failed, a nullopt
*/
-std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutput> coins,
+std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, const std::vector<COutput>& available_coins,
const CoinSelectionParams& coin_selection_params);
/**
* Select a set of coins such that nTargetValue is met and at least
* all coins from coin_control are selected; never select unconfirmed coins if they are not ours
* param@[in] wallet The wallet which provides data necessary to spend the selected coins
- * param@[in] vAvailableCoins The vector of coins available to be spent
+ * param@[in] available_coins The struct of coins, organized by OutputType, available for selection prior to filtering
* param@[in] nTargetValue The target value
* param@[in] coin_selection_params Parameters for this coin selection such as feerates, whether to avoid partial spends,
* and whether to subtract the fee from the outputs.
* returns If successful, a SelectionResult containing the selected coins
* If failed, a nullopt.
*/
-std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, const CCoinControl& coin_control,
+std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CCoinControl& coin_control,
const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
struct CreatedTransactionResult
{
CTransactionRef tx;
CAmount fee;
+ FeeCalculation fee_calc;
int change_pos;
- CreatedTransactionResult(CTransactionRef tx, CAmount fee, int change_pos)
- : tx(tx), fee(fee), change_pos(change_pos) {}
+ CreatedTransactionResult(CTransactionRef _tx, CAmount _fee, int _change_pos, const FeeCalculation& _fee_calc)
+ : tx(_tx), fee(_fee), fee_calc(_fee_calc), change_pos(_change_pos) {}
};
/**
@@ -118,7 +151,7 @@ struct CreatedTransactionResult
* selected by SelectCoins(); Also create the change output, when needed
* @note passing change_pos as -1 will result in setting a random position
*/
-std::optional<CreatedTransactionResult> CreateTransaction(CWallet& wallet, const std::vector<CRecipient>& vecSend, int change_pos, bilingual_str& error, const CCoinControl& coin_control, FeeCalculation& fee_calc_out, bool sign = true);
+util::Result<CreatedTransactionResult> CreateTransaction(CWallet& wallet, const std::vector<CRecipient>& vecSend, int change_pos, const CCoinControl& coin_control, bool sign = true);
/**
* Insert additional inputs into the transaction by
diff --git a/src/wallet/test/availablecoins_tests.cpp b/src/wallet/test/availablecoins_tests.cpp
new file mode 100644
index 0000000000..2427a343d5
--- /dev/null
+++ b/src/wallet/test/availablecoins_tests.cpp
@@ -0,0 +1,107 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or https://www.opensource.org/licenses/mit-license.php.
+
+#include <validation.h>
+#include <wallet/coincontrol.h>
+#include <wallet/spend.h>
+#include <wallet/test/util.h>
+#include <wallet/test/wallet_test_fixture.h>
+
+#include <boost/test/unit_test.hpp>
+
+namespace wallet {
+BOOST_FIXTURE_TEST_SUITE(availablecoins_tests, WalletTestingSetup)
+class AvailableCoinsTestingSetup : public TestChain100Setup
+{
+public:
+ AvailableCoinsTestingSetup()
+ {
+ CreateAndProcessBlock({}, {});
+ wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey);
+ }
+
+ ~AvailableCoinsTestingSetup()
+ {
+ wallet.reset();
+ }
+ CWalletTx& AddTx(CRecipient recipient)
+ {
+ CTransactionRef tx;
+ CCoinControl dummy;
+ {
+ constexpr int RANDOM_CHANGE_POSITION = -1;
+ auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, dummy);
+ BOOST_CHECK(res);
+ tx = res->tx;
+ }
+ wallet->CommitTransaction(tx, {}, {});
+ CMutableTransaction blocktx;
+ {
+ LOCK(wallet->cs_wallet);
+ blocktx = CMutableTransaction(*wallet->mapWallet.at(tx->GetHash()).tx);
+ }
+ CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+
+ LOCK(wallet->cs_wallet);
+ LOCK(m_node.chainman->GetMutex());
+ wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
+ auto it = wallet->mapWallet.find(tx->GetHash());
+ BOOST_CHECK(it != wallet->mapWallet.end());
+ it->second.m_state = TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/1};
+ return it->second;
+ }
+
+ std::unique_ptr<CWallet> wallet;
+};
+
+BOOST_FIXTURE_TEST_CASE(BasicOutputTypesTest, AvailableCoinsTestingSetup)
+{
+ CoinsResult available_coins;
+ util::Result<CTxDestination> dest{util::Error{}};
+ LOCK(wallet->cs_wallet);
+
+ // Verify our wallet has one usable coinbase UTXO before starting
+ // This UTXO is a P2PK, so it should show up in the Other bucket
+ available_coins = AvailableCoins(*wallet);
+ BOOST_CHECK_EQUAL(available_coins.Size(), 1U);
+ BOOST_CHECK_EQUAL(available_coins.coins[OutputType::UNKNOWN].size(), 1U);
+
+ // We will create a self transfer for each of the OutputTypes and
+ // verify it is put in the correct bucket after running GetAvailablecoins
+ //
+ // For each OutputType, We expect 2 UTXOs in our wallet following the self transfer:
+ // 1. One UTXO as the recipient
+ // 2. One UTXO from the change, due to payment address matching logic
+
+ // Bech32m
+ dest = wallet->GetNewDestination(OutputType::BECH32M, "");
+ BOOST_ASSERT(dest);
+ AddTx(CRecipient{{GetScriptForDestination(*dest)}, 1 * COIN, /*fSubtractFeeFromAmount=*/true});
+ available_coins = AvailableCoins(*wallet);
+ BOOST_CHECK_EQUAL(available_coins.coins[OutputType::BECH32M].size(), 2U);
+
+ // Bech32
+ dest = wallet->GetNewDestination(OutputType::BECH32, "");
+ BOOST_ASSERT(dest);
+ AddTx(CRecipient{{GetScriptForDestination(*dest)}, 2 * COIN, /*fSubtractFeeFromAmount=*/true});
+ available_coins = AvailableCoins(*wallet);
+ BOOST_CHECK_EQUAL(available_coins.coins[OutputType::BECH32].size(), 2U);
+
+ // P2SH-SEGWIT
+ dest = wallet->GetNewDestination(OutputType::P2SH_SEGWIT, "");
+ BOOST_ASSERT(dest);
+ AddTx(CRecipient{{GetScriptForDestination(*dest)}, 3 * COIN, /*fSubtractFeeFromAmount=*/true});
+ available_coins = AvailableCoins(*wallet);
+ BOOST_CHECK_EQUAL(available_coins.coins[OutputType::P2SH_SEGWIT].size(), 2U);
+
+ // Legacy (P2PKH)
+ dest = wallet->GetNewDestination(OutputType::LEGACY, "");
+ BOOST_ASSERT(dest);
+ AddTx(CRecipient{{GetScriptForDestination(*dest)}, 4 * COIN, /*fSubtractFeeFromAmount=*/true});
+ available_coins = AvailableCoins(*wallet);
+ BOOST_CHECK_EQUAL(available_coins.coins[OutputType::LEGACY].size(), 2U);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+} // namespace wallet
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index d6f47e9954..9bc6fafae7 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -67,18 +67,14 @@ static void add_coin(const CAmount& nValue, int nInput, CoinSet& set, CAmount fe
set.insert(coin);
}
-static void add_coin(std::vector<COutput>& coins, CWallet& wallet, const CAmount& nValue, CFeeRate feerate = CFeeRate(0), int nAge = 6*24, bool fIsFromMe = false, int nInput=0, bool spendable = false)
+static void add_coin(CoinsResult& available_coins, CWallet& wallet, const CAmount& nValue, CFeeRate feerate = CFeeRate(0), int nAge = 6*24, bool fIsFromMe = false, int nInput =0, bool spendable = false)
{
CMutableTransaction tx;
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
tx.vout.resize(nInput + 1);
tx.vout[nInput].nValue = nValue;
if (spendable) {
- CTxDestination dest;
- bilingual_str error;
- const bool destination_ok = wallet.GetNewDestination(OutputType::BECH32, "", dest, error);
- assert(destination_ok);
- tx.vout[nInput].scriptPubKey = GetScriptForDestination(dest);
+ tx.vout[nInput].scriptPubKey = GetScriptForDestination(*Assert(wallet.GetNewDestination(OutputType::BECH32, "")));
}
uint256 txid = tx.GetHash();
@@ -86,7 +82,8 @@ static void add_coin(std::vector<COutput>& coins, CWallet& wallet, const CAmount
auto ret = wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(txid), std::forward_as_tuple(MakeTransactionRef(std::move(tx)), TxStateInactive{}));
assert(ret.second);
CWalletTx& wtx = (*ret.first).second;
- coins.emplace_back(COutPoint(wtx.GetHash(), nInput), wtx.tx->vout.at(nInput), nAge, GetTxSpendSize(wallet, wtx, nInput), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ true, wtx.GetTxTime(), fIsFromMe, feerate);
+ const auto& txout = wtx.tx->vout.at(nInput);
+ available_coins.coins[OutputType::BECH32].emplace_back(COutPoint(wtx.GetHash(), nInput), txout, nAge, CalculateMaximumSignedInputSize(txout, &wallet, /*coin_control=*/nullptr), /*spendable=*/ true, /*solvable=*/ true, /*safe=*/ true, wtx.GetTxTime(), fIsFromMe, feerate);
}
/** Check if SelectionResult a is equivalent to SelectionResult b.
@@ -130,18 +127,18 @@ static CAmount make_hard_case(int utxos, std::vector<COutput>& utxo_pool)
return target;
}
-inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& coins)
+inline std::vector<OutputGroup>& GroupCoins(const std::vector<COutput>& available_coins)
{
static std::vector<OutputGroup> static_groups;
static_groups.clear();
- for (auto& coin : coins) {
+ for (auto& coin : available_coins) {
static_groups.emplace_back();
static_groups.back().Insert(coin, /*ancestors=*/ 0, /*descendants=*/ 0, /*positive_only=*/ false);
}
return static_groups;
}
-inline std::vector<OutputGroup>& KnapsackGroupOutputs(const std::vector<COutput>& coins, CWallet& wallet, const CoinEligibilityFilter& filter)
+inline std::vector<OutputGroup>& KnapsackGroupOutputs(const std::vector<COutput>& available_coins, CWallet& wallet, const CoinEligibilityFilter& filter)
{
FastRandomContext rand{};
CoinSelectionParams coin_selection_params{
@@ -156,7 +153,7 @@ inline std::vector<OutputGroup>& KnapsackGroupOutputs(const std::vector<COutput>
/*avoid_partial=*/ false,
};
static std::vector<OutputGroup> static_groups;
- static_groups = GroupOutputs(wallet, coins, coin_selection_params, filter, /*positive_only=*/false);
+ static_groups = GroupOutputs(wallet, available_coins, coin_selection_params, filter, /*positive_only=*/false);
return static_groups;
}
@@ -198,8 +195,8 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
expected_result.Clear();
// Select 5 Cent
- add_coin(4 * CENT, 4, expected_result);
- add_coin(1 * CENT, 1, expected_result);
+ add_coin(3 * CENT, 3, expected_result);
+ add_coin(2 * CENT, 2, expected_result);
const auto result3 = SelectCoinsBnB(GroupCoins(utxo_pool), 5 * CENT, 0.5 * CENT);
BOOST_CHECK(result3);
BOOST_CHECK(EquivalentResult(expected_result, *result3));
@@ -224,8 +221,9 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
// Select 10 Cent
add_coin(5 * CENT, 5, utxo_pool);
- add_coin(5 * CENT, 5, expected_result);
add_coin(4 * CENT, 4, expected_result);
+ add_coin(3 * CENT, 3, expected_result);
+ add_coin(2 * CENT, 2, expected_result);
add_coin(1 * CENT, 1, expected_result);
const auto result5 = SelectCoinsBnB(GroupCoins(utxo_pool), 10 * CENT, 0.5 * CENT);
BOOST_CHECK(result5);
@@ -250,9 +248,9 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
// Iteration exhaustion test
CAmount target = make_hard_case(17, utxo_pool);
- BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), target, 0)); // Should exhaust
+ BOOST_CHECK(!SelectCoinsBnB(GroupCoins(utxo_pool), target, 1)); // Should exhaust
target = make_hard_case(14, utxo_pool);
- const auto result7 = SelectCoinsBnB(GroupCoins(utxo_pool), target, 0); // Should not exhaust
+ const auto result7 = SelectCoinsBnB(GroupCoins(utxo_pool), target, 1); // Should not exhaust
BOOST_CHECK(result7);
// Test same value early bailout optimization
@@ -291,8 +289,8 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
// Make sure that effective value is working in AttemptSelection when BnB is used
CoinSelectionParams coin_selection_params_bnb{
rand,
- /*change_output_size=*/ 0,
- /*change_spend_size=*/ 0,
+ /*change_output_size=*/ 31,
+ /*change_spend_size=*/ 68,
/*min_change_target=*/ 0,
/*effective_feerate=*/ CFeeRate(3000),
/*long_term_feerate=*/ CFeeRate(1000),
@@ -300,6 +298,9 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
/*tx_noinputs_size=*/ 0,
/*avoid_partial=*/ false,
};
+ coin_selection_params_bnb.m_change_fee = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_output_size);
+ coin_selection_params_bnb.m_cost_of_change = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_spend_size) + coin_selection_params_bnb.m_change_fee;
+ coin_selection_params_bnb.min_viable_change = coin_selection_params_bnb.m_effective_feerate.GetFee(coin_selection_params_bnb.change_spend_size);
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
wallet->LoadWallet();
@@ -307,18 +308,18 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
- add_coin(coins, *wallet, 1, coin_selection_params_bnb.m_effective_feerate);
- coins.at(0).input_bytes = 40; // Make sure that it has a negative effective value. The next check should assert if this somehow got through. Otherwise it will fail
- BOOST_CHECK(!SelectCoinsBnB(GroupCoins(coins), 1 * CENT, coin_selection_params_bnb.m_cost_of_change));
+ add_coin(available_coins, *wallet, 1, coin_selection_params_bnb.m_effective_feerate);
+ available_coins.All().at(0).input_bytes = 40; // Make sure that it has a negative effective value. The next check should assert if this somehow got through. Otherwise it will fail
+ BOOST_CHECK(!SelectCoinsBnB(GroupCoins(available_coins.All()), 1 * CENT, coin_selection_params_bnb.m_cost_of_change));
// Test fees subtracted from output:
- coins.clear();
- add_coin(coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate);
- coins.at(0).input_bytes = 40;
+ available_coins.Clear();
+ add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate);
+ available_coins.All().at(0).input_bytes = 40;
coin_selection_params_bnb.m_subtract_fee_outputs = true;
- const auto result9 = SelectCoinsBnB(GroupCoins(coins), 1 * CENT, coin_selection_params_bnb.m_cost_of_change);
+ const auto result9 = SelectCoinsBnB(GroupCoins(available_coins.All()), 1 * CENT, coin_selection_params_bnb.m_cost_of_change);
BOOST_CHECK(result9);
BOOST_CHECK_EQUAL(result9->GetSelectedValue(), 1 * CENT);
}
@@ -330,16 +331,16 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
- add_coin(coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 3 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 2 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 5 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 3 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 2 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
CCoinControl coin_control;
coin_control.m_allow_other_inputs = true;
- coin_control.Select(coins.at(0).outpoint);
+ coin_control.Select(available_coins.All().at(0).outpoint);
coin_selection_params_bnb.m_effective_feerate = CFeeRate(0);
- const auto result10 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
+ const auto result10 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(result10);
}
{
@@ -349,52 +350,52 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
// single coin should be selected when effective fee > long term fee
coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000);
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(3000);
- add_coin(coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
expected_result.Clear();
add_coin(10 * CENT, 2, expected_result);
CCoinControl coin_control;
- const auto result11 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
+ const auto result11 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(EquivalentResult(expected_result, *result11));
- coins.clear();
+ available_coins.Clear();
// more coins should be selected when effective fee < long term fee
coin_selection_params_bnb.m_effective_feerate = CFeeRate(3000);
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(5000);
- add_coin(coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
expected_result.Clear();
add_coin(9 * CENT, 2, expected_result);
add_coin(1 * CENT, 2, expected_result);
- const auto result12 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
+ const auto result12 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(EquivalentResult(expected_result, *result12));
- coins.clear();
+ available_coins.Clear();
// pre selected coin should be selected even if disadvantageous
coin_selection_params_bnb.m_effective_feerate = CFeeRate(5000);
coin_selection_params_bnb.m_long_term_feerate = CFeeRate(3000);
- add_coin(coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
- add_coin(coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 10 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 9 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
+ add_coin(available_coins, *wallet, 1 * CENT, coin_selection_params_bnb.m_effective_feerate, 6 * 24, false, 0, true);
expected_result.Clear();
add_coin(9 * CENT, 2, expected_result);
add_coin(1 * CENT, 2, expected_result);
coin_control.m_allow_other_inputs = true;
- coin_control.Select(coins.at(1).outpoint); // pre select 9 coin
- const auto result13 = SelectCoins(*wallet, coins, 10 * CENT, coin_control, coin_selection_params_bnb);
+ coin_control.Select(available_coins.All().at(1).outpoint); // pre select 9 coin
+ const auto result13 = SelectCoins(*wallet, available_coins, 10 * CENT, coin_control, coin_selection_params_bnb);
BOOST_CHECK(EquivalentResult(expected_result, *result13));
}
}
@@ -410,175 +411,175 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
// test multiple times to allow for differences in the shuffle order
for (int i = 0; i < RUN_TESTS; i++)
{
- coins.clear();
+ available_coins.Clear();
// with an empty wallet we can't even pay one cent
- BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 1 * CENT, CENT));
+ BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 1 * CENT, CENT));
- add_coin(coins, *wallet, 1*CENT, CFeeRate(0), 4); // add a new 1 cent coin
+ add_coin(available_coins, *wallet, 1*CENT, CFeeRate(0), 4); // add a new 1 cent coin
// with a new 1 cent coin, we still can't find a mature 1 cent
- BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 1 * CENT, CENT));
+ BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 1 * CENT, CENT));
// but we can find a new 1 cent
- const auto result1 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 1 * CENT, CENT);
+ const auto result1 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 1 * CENT, CENT);
BOOST_CHECK(result1);
BOOST_CHECK_EQUAL(result1->GetSelectedValue(), 1 * CENT);
- add_coin(coins, *wallet, 2*CENT); // add a mature 2 cent coin
+ add_coin(available_coins, *wallet, 2*CENT); // add a mature 2 cent coin
// we can't make 3 cents of mature coins
- BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 3 * CENT, CENT));
+ BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 3 * CENT, CENT));
// we can make 3 cents of new coins
- const auto result2 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 3 * CENT, CENT);
+ const auto result2 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 3 * CENT, CENT);
BOOST_CHECK(result2);
BOOST_CHECK_EQUAL(result2->GetSelectedValue(), 3 * CENT);
- add_coin(coins, *wallet, 5*CENT); // add a mature 5 cent coin,
- add_coin(coins, *wallet, 10*CENT, CFeeRate(0), 3, true); // a new 10 cent coin sent from one of our own addresses
- add_coin(coins, *wallet, 20*CENT); // and a mature 20 cent coin
+ add_coin(available_coins, *wallet, 5*CENT); // add a mature 5 cent coin,
+ add_coin(available_coins, *wallet, 10*CENT, CFeeRate(0), 3, true); // a new 10 cent coin sent from one of our own addresses
+ add_coin(available_coins, *wallet, 20*CENT); // and a mature 20 cent coin
// now we have new: 1+10=11 (of which 10 was self-sent), and mature: 2+5+20=27. total = 38
// we can't make 38 cents only if we disallow new coins:
- BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 38 * CENT, CENT));
+ BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 38 * CENT, CENT));
// we can't even make 37 cents if we don't allow new coins even if they're from us
- BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard_extra), 38 * CENT, CENT));
+ BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard_extra), 38 * CENT, CENT));
// but we can make 37 cents if we accept new coins from ourself
- const auto result3 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 37 * CENT, CENT);
+ const auto result3 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 37 * CENT, CENT);
BOOST_CHECK(result3);
BOOST_CHECK_EQUAL(result3->GetSelectedValue(), 37 * CENT);
// and we can make 38 cents if we accept all new coins
- const auto result4 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 38 * CENT, CENT);
+ const auto result4 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 38 * CENT, CENT);
BOOST_CHECK(result4);
BOOST_CHECK_EQUAL(result4->GetSelectedValue(), 38 * CENT);
// try making 34 cents from 1,2,5,10,20 - we can't do it exactly
- const auto result5 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 34 * CENT, CENT);
+ const auto result5 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 34 * CENT, CENT);
BOOST_CHECK(result5);
BOOST_CHECK_EQUAL(result5->GetSelectedValue(), 35 * CENT); // but 35 cents is closest
BOOST_CHECK_EQUAL(result5->GetInputSet().size(), 3U); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible)
// when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5
- const auto result6 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 7 * CENT, CENT);
+ const auto result6 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 7 * CENT, CENT);
BOOST_CHECK(result6);
BOOST_CHECK_EQUAL(result6->GetSelectedValue(), 7 * CENT);
BOOST_CHECK_EQUAL(result6->GetInputSet().size(), 2U);
// when we try making 8 cents, the smaller coins (1,2,5) are exactly enough.
- const auto result7 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 8 * CENT, CENT);
+ const auto result7 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 8 * CENT, CENT);
BOOST_CHECK(result7);
BOOST_CHECK(result7->GetSelectedValue() == 8 * CENT);
BOOST_CHECK_EQUAL(result7->GetInputSet().size(), 3U);
// when we try making 9 cents, no subset of smaller coins is enough, and we get the next bigger coin (10)
- const auto result8 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 9 * CENT, CENT);
+ const auto result8 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 9 * CENT, CENT);
BOOST_CHECK(result8);
BOOST_CHECK_EQUAL(result8->GetSelectedValue(), 10 * CENT);
BOOST_CHECK_EQUAL(result8->GetInputSet().size(), 1U);
// now clear out the wallet and start again to test choosing between subsets of smaller coins and the next biggest coin
- coins.clear();
+ available_coins.Clear();
- add_coin(coins, *wallet, 6*CENT);
- add_coin(coins, *wallet, 7*CENT);
- add_coin(coins, *wallet, 8*CENT);
- add_coin(coins, *wallet, 20*CENT);
- add_coin(coins, *wallet, 30*CENT); // now we have 6+7+8+20+30 = 71 cents total
+ add_coin(available_coins, *wallet, 6*CENT);
+ add_coin(available_coins, *wallet, 7*CENT);
+ add_coin(available_coins, *wallet, 8*CENT);
+ add_coin(available_coins, *wallet, 20*CENT);
+ add_coin(available_coins, *wallet, 30*CENT); // now we have 6+7+8+20+30 = 71 cents total
// check that we have 71 and not 72
- const auto result9 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 71 * CENT, CENT);
+ const auto result9 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 71 * CENT, CENT);
BOOST_CHECK(result9);
- BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 72 * CENT, CENT));
+ BOOST_CHECK(!KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 72 * CENT, CENT));
// now try making 16 cents. the best smaller coins can do is 6+7+8 = 21; not as good at the next biggest coin, 20
- const auto result10 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 16 * CENT, CENT);
+ const auto result10 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 16 * CENT, CENT);
BOOST_CHECK(result10);
BOOST_CHECK_EQUAL(result10->GetSelectedValue(), 20 * CENT); // we should get 20 in one coin
BOOST_CHECK_EQUAL(result10->GetInputSet().size(), 1U);
- add_coin(coins, *wallet, 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total
+ add_coin(available_coins, *wallet, 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total
// now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, better than the next biggest coin, 20
- const auto result11 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 16 * CENT, CENT);
+ const auto result11 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 16 * CENT, CENT);
BOOST_CHECK(result11);
BOOST_CHECK_EQUAL(result11->GetSelectedValue(), 18 * CENT); // we should get 18 in 3 coins
BOOST_CHECK_EQUAL(result11->GetInputSet().size(), 3U);
- add_coin(coins, *wallet, 18*CENT); // now we have 5+6+7+8+18+20+30
+ add_coin(available_coins, *wallet, 18*CENT); // now we have 5+6+7+8+18+20+30
// and now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, the same as the next biggest coin, 18
- const auto result12 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 16 * CENT, CENT);
+ const auto result12 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 16 * CENT, CENT);
BOOST_CHECK(result12);
BOOST_CHECK_EQUAL(result12->GetSelectedValue(), 18 * CENT); // we should get 18 in 1 coin
BOOST_CHECK_EQUAL(result12->GetInputSet().size(), 1U); // because in the event of a tie, the biggest coin wins
// now try making 11 cents. we should get 5+6
- const auto result13 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 11 * CENT, CENT);
+ const auto result13 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 11 * CENT, CENT);
BOOST_CHECK(result13);
BOOST_CHECK_EQUAL(result13->GetSelectedValue(), 11 * CENT);
BOOST_CHECK_EQUAL(result13->GetInputSet().size(), 2U);
// check that the smallest bigger coin is used
- add_coin(coins, *wallet, 1*COIN);
- add_coin(coins, *wallet, 2*COIN);
- add_coin(coins, *wallet, 3*COIN);
- add_coin(coins, *wallet, 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents
- const auto result14 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 95 * CENT, CENT);
+ add_coin(available_coins, *wallet, 1*COIN);
+ add_coin(available_coins, *wallet, 2*COIN);
+ add_coin(available_coins, *wallet, 3*COIN);
+ add_coin(available_coins, *wallet, 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents
+ const auto result14 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 95 * CENT, CENT);
BOOST_CHECK(result14);
BOOST_CHECK_EQUAL(result14->GetSelectedValue(), 1 * COIN); // we should get 1 BTC in 1 coin
BOOST_CHECK_EQUAL(result14->GetInputSet().size(), 1U);
- const auto result15 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 195 * CENT, CENT);
+ const auto result15 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 195 * CENT, CENT);
BOOST_CHECK(result15);
BOOST_CHECK_EQUAL(result15->GetSelectedValue(), 2 * COIN); // we should get 2 BTC in 1 coin
BOOST_CHECK_EQUAL(result15->GetInputSet().size(), 1U);
// empty the wallet and start again, now with fractions of a cent, to test small change avoidance
- coins.clear();
- add_coin(coins, *wallet, CENT * 1 / 10);
- add_coin(coins, *wallet, CENT * 2 / 10);
- add_coin(coins, *wallet, CENT * 3 / 10);
- add_coin(coins, *wallet, CENT * 4 / 10);
- add_coin(coins, *wallet, CENT * 5 / 10);
+ available_coins.Clear();
+ add_coin(available_coins, *wallet, CENT * 1 / 10);
+ add_coin(available_coins, *wallet, CENT * 2 / 10);
+ add_coin(available_coins, *wallet, CENT * 3 / 10);
+ add_coin(available_coins, *wallet, CENT * 4 / 10);
+ add_coin(available_coins, *wallet, CENT * 5 / 10);
// try making 1 * CENT from the 1.5 * CENT
// we'll get change smaller than CENT whatever happens, so can expect CENT exactly
- const auto result16 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), CENT, CENT);
+ const auto result16 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), CENT, CENT);
BOOST_CHECK(result16);
BOOST_CHECK_EQUAL(result16->GetSelectedValue(), CENT);
// but if we add a bigger coin, small change is avoided
- add_coin(coins, *wallet, 1111*CENT);
+ add_coin(available_coins, *wallet, 1111*CENT);
// try making 1 from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5
- const auto result17 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 1 * CENT, CENT);
+ const auto result17 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 1 * CENT, CENT);
BOOST_CHECK(result17);
BOOST_CHECK_EQUAL(result17->GetSelectedValue(), 1 * CENT); // we should get the exact amount
// if we add more small coins:
- add_coin(coins, *wallet, CENT * 6 / 10);
- add_coin(coins, *wallet, CENT * 7 / 10);
+ add_coin(available_coins, *wallet, CENT * 6 / 10);
+ add_coin(available_coins, *wallet, CENT * 7 / 10);
// and try again to make 1.0 * CENT
- const auto result18 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 1 * CENT, CENT);
+ const auto result18 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 1 * CENT, CENT);
BOOST_CHECK(result18);
BOOST_CHECK_EQUAL(result18->GetSelectedValue(), 1 * CENT); // we should get the exact amount
// run the 'mtgox' test (see https://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf)
// they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change
- coins.clear();
+ available_coins.Clear();
for (int j = 0; j < 20; j++)
- add_coin(coins, *wallet, 50000 * COIN);
+ add_coin(available_coins, *wallet, 50000 * COIN);
- const auto result19 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 500000 * COIN, CENT);
+ const auto result19 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 500000 * COIN, CENT);
BOOST_CHECK(result19);
BOOST_CHECK_EQUAL(result19->GetSelectedValue(), 500000 * COIN); // we should get the exact amount
BOOST_CHECK_EQUAL(result19->GetInputSet().size(), 10U); // in ten coins
@@ -587,41 +588,41 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
// we need to try finding an exact subset anyway
// sometimes it will fail, and so we use the next biggest coin:
- coins.clear();
- add_coin(coins, *wallet, CENT * 5 / 10);
- add_coin(coins, *wallet, CENT * 6 / 10);
- add_coin(coins, *wallet, CENT * 7 / 10);
- add_coin(coins, *wallet, 1111 * CENT);
- const auto result20 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 1 * CENT, CENT);
+ available_coins.Clear();
+ add_coin(available_coins, *wallet, CENT * 5 / 10);
+ add_coin(available_coins, *wallet, CENT * 6 / 10);
+ add_coin(available_coins, *wallet, CENT * 7 / 10);
+ add_coin(available_coins, *wallet, 1111 * CENT);
+ const auto result20 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 1 * CENT, CENT);
BOOST_CHECK(result20);
BOOST_CHECK_EQUAL(result20->GetSelectedValue(), 1111 * CENT); // we get the bigger coin
BOOST_CHECK_EQUAL(result20->GetInputSet().size(), 1U);
// but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0)
- coins.clear();
- add_coin(coins, *wallet, CENT * 4 / 10);
- add_coin(coins, *wallet, CENT * 6 / 10);
- add_coin(coins, *wallet, CENT * 8 / 10);
- add_coin(coins, *wallet, 1111 * CENT);
- const auto result21 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), CENT, CENT);
+ available_coins.Clear();
+ add_coin(available_coins, *wallet, CENT * 4 / 10);
+ add_coin(available_coins, *wallet, CENT * 6 / 10);
+ add_coin(available_coins, *wallet, CENT * 8 / 10);
+ add_coin(available_coins, *wallet, 1111 * CENT);
+ const auto result21 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), CENT, CENT);
BOOST_CHECK(result21);
BOOST_CHECK_EQUAL(result21->GetSelectedValue(), CENT); // we should get the exact amount
BOOST_CHECK_EQUAL(result21->GetInputSet().size(), 2U); // in two coins 0.4+0.6
// test avoiding small change
- coins.clear();
- add_coin(coins, *wallet, CENT * 5 / 100);
- add_coin(coins, *wallet, CENT * 1);
- add_coin(coins, *wallet, CENT * 100);
+ available_coins.Clear();
+ add_coin(available_coins, *wallet, CENT * 5 / 100);
+ add_coin(available_coins, *wallet, CENT * 1);
+ add_coin(available_coins, *wallet, CENT * 100);
// trying to make 100.01 from these three coins
- const auto result22 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), CENT * 10001 / 100, CENT);
+ const auto result22 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), CENT * 10001 / 100, CENT);
BOOST_CHECK(result22);
BOOST_CHECK_EQUAL(result22->GetSelectedValue(), CENT * 10105 / 100); // we should get all coins
BOOST_CHECK_EQUAL(result22->GetInputSet().size(), 3U);
// but if we try to make 99.9, we should take the bigger of the two small coins to avoid small change
- const auto result23 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), CENT * 9990 / 100, CENT);
+ const auto result23 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), CENT * 9990 / 100, CENT);
BOOST_CHECK(result23);
BOOST_CHECK_EQUAL(result23->GetSelectedValue(), 101 * CENT);
BOOST_CHECK_EQUAL(result23->GetInputSet().size(), 2U);
@@ -629,14 +630,14 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
// test with many inputs
for (CAmount amt=1500; amt < COIN; amt*=10) {
- coins.clear();
+ available_coins.Clear();
// Create 676 inputs (= (old MAX_STANDARD_TX_SIZE == 100000) / 148 bytes per input)
for (uint16_t j = 0; j < 676; j++)
- add_coin(coins, *wallet, amt);
+ add_coin(available_coins, *wallet, amt);
// We only create the wallet once to save time, but we still run the coin selection RUN_TESTS times.
for (int i = 0; i < RUN_TESTS; i++) {
- const auto result24 = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_confirmed), 2000, CENT);
+ const auto result24 = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_confirmed), 2000, CENT);
BOOST_CHECK(result24);
if (amt - 2000 < CENT) {
@@ -655,17 +656,17 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
// test randomness
{
- coins.clear();
+ available_coins.Clear();
for (int i2 = 0; i2 < 100; i2++)
- add_coin(coins, *wallet, COIN);
+ add_coin(available_coins, *wallet, COIN);
// Again, we only create the wallet once to save time, but we still run the coin selection RUN_TESTS times.
for (int i = 0; i < RUN_TESTS; i++) {
// picking 50 from 100 coins doesn't depend on the shuffle,
// but does depend on randomness in the stochastic approximation code
- const auto result25 = KnapsackSolver(GroupCoins(coins), 50 * COIN, CENT);
+ const auto result25 = KnapsackSolver(GroupCoins(available_coins.All()), 50 * COIN, CENT);
BOOST_CHECK(result25);
- const auto result26 = KnapsackSolver(GroupCoins(coins), 50 * COIN, CENT);
+ const auto result26 = KnapsackSolver(GroupCoins(available_coins.All()), 50 * COIN, CENT);
BOOST_CHECK(result26);
BOOST_CHECK(!EqualResult(*result25, *result26));
@@ -676,9 +677,9 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
// When choosing 1 from 100 identical coins, 1% of the time, this test will choose the same coin twice
// which will cause it to fail.
// To avoid that issue, run the test RANDOM_REPEATS times and only complain if all of them fail
- const auto result27 = KnapsackSolver(GroupCoins(coins), COIN, CENT);
+ const auto result27 = KnapsackSolver(GroupCoins(available_coins.All()), COIN, CENT);
BOOST_CHECK(result27);
- const auto result28 = KnapsackSolver(GroupCoins(coins), COIN, CENT);
+ const auto result28 = KnapsackSolver(GroupCoins(available_coins.All()), COIN, CENT);
BOOST_CHECK(result28);
if (EqualResult(*result27, *result28))
fails++;
@@ -689,19 +690,19 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
// add 75 cents in small change. not enough to make 90 cents,
// then try making 90 cents. there are multiple competing "smallest bigger" coins,
// one of which should be picked at random
- add_coin(coins, *wallet, 5 * CENT);
- add_coin(coins, *wallet, 10 * CENT);
- add_coin(coins, *wallet, 15 * CENT);
- add_coin(coins, *wallet, 20 * CENT);
- add_coin(coins, *wallet, 25 * CENT);
+ add_coin(available_coins, *wallet, 5 * CENT);
+ add_coin(available_coins, *wallet, 10 * CENT);
+ add_coin(available_coins, *wallet, 15 * CENT);
+ add_coin(available_coins, *wallet, 20 * CENT);
+ add_coin(available_coins, *wallet, 25 * CENT);
for (int i = 0; i < RUN_TESTS; i++) {
int fails = 0;
for (int j = 0; j < RANDOM_REPEATS; j++)
{
- const auto result29 = KnapsackSolver(GroupCoins(coins), 90 * CENT, CENT);
+ const auto result29 = KnapsackSolver(GroupCoins(available_coins.All()), 90 * CENT, CENT);
BOOST_CHECK(result29);
- const auto result30 = KnapsackSolver(GroupCoins(coins), 90 * CENT, CENT);
+ const auto result30 = KnapsackSolver(GroupCoins(available_coins.All()), 90 * CENT, CENT);
BOOST_CHECK(result30);
if (EqualResult(*result29, *result30))
fails++;
@@ -720,14 +721,14 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetupDescriptorScriptPubKeyMans();
- std::vector<COutput> coins;
+ CoinsResult available_coins;
// Test vValue sort order
for (int i = 0; i < 1000; i++)
- add_coin(coins, *wallet, 1000 * COIN);
- add_coin(coins, *wallet, 3 * COIN);
+ add_coin(available_coins, *wallet, 1000 * COIN);
+ add_coin(available_coins, *wallet, 3 * COIN);
- const auto result = KnapsackSolver(KnapsackGroupOutputs(coins, *wallet, filter_standard), 1003 * COIN, CENT, rand);
+ const auto result = KnapsackSolver(KnapsackGroupOutputs(available_coins.All(), *wallet, filter_standard), 1003 * COIN, CENT, rand);
BOOST_CHECK(result);
BOOST_CHECK_EQUAL(result->GetSelectedValue(), 1003 * COIN);
BOOST_CHECK_EQUAL(result->GetInputSet().size(), 2U);
@@ -750,14 +751,14 @@ BOOST_AUTO_TEST_CASE(SelectCoins_test)
// Run this test 100 times
for (int i = 0; i < 100; ++i)
{
- std::vector<COutput> coins;
+ CoinsResult available_coins;
CAmount balance{0};
// Make a wallet with 1000 exponentially distributed random inputs
for (int j = 0; j < 1000; ++j)
{
CAmount val = distribution(generator)*10000000;
- add_coin(coins, *wallet, val);
+ add_coin(available_coins, *wallet, val);
balance += val;
}
@@ -779,8 +780,10 @@ BOOST_AUTO_TEST_CASE(SelectCoins_test)
/*tx_noinputs_size=*/ 0,
/*avoid_partial=*/ false,
};
+ cs_params.m_cost_of_change = 1;
+ cs_params.min_viable_change = 1;
CCoinControl cc;
- const auto result = SelectCoins(*wallet, coins, target, cc, cs_params);
+ const auto result = SelectCoins(*wallet, available_coins, target, cc, cs_params);
BOOST_CHECK(result);
BOOST_CHECK_GE(result->GetSelectedValue(), target);
}
@@ -865,7 +868,23 @@ BOOST_AUTO_TEST_CASE(waste_test)
const CAmount new_target{in_amt - fee * 2 - fee_diff * 2};
add_coin(1 * COIN, 1, selection, fee, fee + fee_diff);
add_coin(2 * COIN, 2, selection, fee, fee + fee_diff);
- BOOST_CHECK_EQUAL(0, GetSelectionWaste(selection, /* change cost */ 0, new_target));
+ BOOST_CHECK_EQUAL(0, GetSelectionWaste(selection, /*change_cost=*/ 0, new_target));
+ selection.clear();
+
+ // Negative waste when the long term fee is greater than the current fee and the selected value == target
+ const CAmount exact_target1{3 * COIN - 2 * fee};
+ const CAmount target_waste1{-2 * fee_diff}; // = (2 * fee) - (2 * (fee + fee_diff))
+ add_coin(1 * COIN, 1, selection, fee, fee + fee_diff);
+ add_coin(2 * COIN, 2, selection, fee, fee + fee_diff);
+ BOOST_CHECK_EQUAL(target_waste1, GetSelectionWaste(selection, /*change_cost=*/ 0, exact_target1));
+ selection.clear();
+
+ // Negative waste when the long term fee is greater than the current fee and change_cost < - (inputs * (fee - long_term_fee))
+ const CAmount large_fee_diff{90};
+ const CAmount target_waste2{-2 * large_fee_diff + change_cost}; // = (2 * fee) - (2 * (fee + large_fee_diff)) + change_cost
+ add_coin(1 * COIN, 1, selection, fee, fee + large_fee_diff);
+ add_coin(2 * COIN, 2, selection, fee, fee + large_fee_diff);
+ BOOST_CHECK_EQUAL(target_waste2, GetSelectionWaste(selection, change_cost, target));
}
BOOST_AUTO_TEST_CASE(effective_value_test)
@@ -903,5 +922,92 @@ BOOST_AUTO_TEST_CASE(effective_value_test)
BOOST_CHECK_EQUAL(output5.GetEffectiveValue(), nValue); // The effective value should be equal to the absolute value if input_bytes is -1
}
+BOOST_AUTO_TEST_CASE(SelectCoins_effective_value_test)
+{
+ // Test that the effective value is used to check whether preset inputs provide sufficient funds when subtract_fee_outputs is not used.
+ // This test creates a coin whose value is higher than the target but whose effective value is lower than the target.
+ // The coin is selected using coin control, with m_allow_other_inputs = false. SelectCoins should fail due to insufficient funds.
+
+ std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
+ wallet->LoadWallet();
+ LOCK(wallet->cs_wallet);
+ wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ wallet->SetupDescriptorScriptPubKeyMans();
+
+ CoinsResult available_coins;
+ {
+ std::unique_ptr<CWallet> dummyWallet = std::make_unique<CWallet>(m_node.chain.get(), "dummy", m_args, CreateMockWalletDatabase());
+ dummyWallet->LoadWallet();
+ LOCK(dummyWallet->cs_wallet);
+ dummyWallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ dummyWallet->SetupDescriptorScriptPubKeyMans();
+
+ add_coin(available_coins, *dummyWallet, 100000); // 0.001 BTC
+ }
+
+ CAmount target{99900}; // 0.000999 BTC
+
+ FastRandomContext rand;
+ CoinSelectionParams cs_params{
+ rand,
+ /*change_output_size=*/34,
+ /*change_spend_size=*/148,
+ /*min_change_target=*/1000,
+ /*effective_feerate=*/CFeeRate(3000),
+ /*long_term_feerate=*/CFeeRate(1000),
+ /*discard_feerate=*/CFeeRate(1000),
+ /*tx_noinputs_size=*/0,
+ /*avoid_partial=*/false,
+ };
+ CCoinControl cc;
+ cc.m_allow_other_inputs = false;
+ COutput output = available_coins.All().at(0);
+ cc.SetInputWeight(output.outpoint, 148);
+ cc.SelectExternal(output.outpoint, output.txout);
+
+ const auto result = SelectCoins(*wallet, available_coins, target, cc, cs_params);
+ BOOST_CHECK(!result);
+}
+
+BOOST_FIXTURE_TEST_CASE(wallet_coinsresult_test, BasicTestingSetup)
+{
+ // Test case to verify CoinsResult object sanity.
+ CoinsResult available_coins;
+ {
+ std::unique_ptr<CWallet> dummyWallet = std::make_unique<CWallet>(m_node.chain.get(), "dummy", m_args, CreateMockWalletDatabase());
+ BOOST_CHECK_EQUAL(dummyWallet->LoadWallet(), DBErrors::LOAD_OK);
+ LOCK(dummyWallet->cs_wallet);
+ dummyWallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ dummyWallet->SetupDescriptorScriptPubKeyMans();
+
+ // Add some coins to 'available_coins'
+ for (int i=0; i<10; i++) {
+ add_coin(available_coins, *dummyWallet, 1 * COIN);
+ }
+ }
+
+ {
+ // First test case, check that 'CoinsResult::Erase' function works as expected.
+ // By trying to erase two elements from the 'available_coins' object.
+ std::set<COutPoint> outs_to_remove;
+ const auto& coins = available_coins.All();
+ for (int i = 0; i < 2; i++) {
+ outs_to_remove.emplace(coins[i].outpoint);
+ }
+ available_coins.Erase(outs_to_remove);
+
+ // Check that the elements were actually removed.
+ const auto& updated_coins = available_coins.All();
+ for (const auto& out: outs_to_remove) {
+ auto it = std::find_if(updated_coins.begin(), updated_coins.end(), [&out](const COutput &coin) {
+ return coin.outpoint == out;
+ });
+ BOOST_CHECK(it == updated_coins.end());
+ }
+ // And verify that no extra element were removed
+ BOOST_CHECK_EQUAL(available_coins.Size(), 8);
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet
diff --git a/src/wallet/test/feebumper_tests.cpp b/src/wallet/test/feebumper_tests.cpp
new file mode 100644
index 0000000000..6add86dc3d
--- /dev/null
+++ b/src/wallet/test/feebumper_tests.cpp
@@ -0,0 +1,54 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or https://www.opensource.org/licenses/mit-license.php.
+
+#include <primitives/transaction.h>
+#include <script/script.h>
+#include <util/strencodings.h>
+#include <wallet/feebumper.h>
+#include <wallet/test/util.h>
+#include <wallet/test/wallet_test_fixture.h>
+
+#include <boost/test/unit_test.hpp>
+
+namespace wallet {
+namespace feebumper {
+BOOST_FIXTURE_TEST_SUITE(feebumper_tests, WalletTestingSetup)
+
+static void CheckMaxWeightComputation(const std::string& script_str, const std::vector<std::string>& witness_str_stack, const std::string& prevout_script_str, int64_t expected_max_weight)
+{
+ std::vector script_data(ParseHex(script_str));
+ CScript script(script_data.begin(), script_data.end());
+ CTxIn input(uint256(), 0, script);
+
+ for (const auto& s : witness_str_stack) {
+ input.scriptWitness.stack.push_back(ParseHex(s));
+ }
+
+ std::vector prevout_script_data(ParseHex(prevout_script_str));
+ CScript prevout_script(prevout_script_data.begin(), prevout_script_data.end());
+
+ int64_t weight = GetTransactionInputWeight(input);
+ SignatureWeights weights;
+ SignatureWeightChecker size_checker(weights, DUMMY_CHECKER);
+ bool script_ok = VerifyScript(input.scriptSig, prevout_script, &input.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, size_checker);
+ BOOST_CHECK(script_ok);
+ weight += weights.GetWeightDiffToMax();
+ BOOST_CHECK_EQUAL(weight, expected_max_weight);
+}
+
+BOOST_AUTO_TEST_CASE(external_max_weight_test)
+{
+ // P2PKH
+ CheckMaxWeightComputation("453042021f03c8957c5ce12940ee6e3333ecc3f633d9a1ac53a55b3ce0351c617fa96abe021f0dccdcce3ef45a63998be9ec748b561baf077b8e862941d0cd5ec08f5afe68012102fccfeb395f0ecd3a77e7bc31c3bc61dc987418b18e395d441057b42ca043f22c", {}, "76a914f60dcfd3392b28adc7662669603641f578eed72d88ac", 593);
+ // P2SH-P2WPKH
+ CheckMaxWeightComputation("160014001dca1b22c599b5a56a87c78417ad2ff39552f1", {"3042021f5443c58eaf45f3e5ef46f8516f966b334a7d497cedda4edb2b9fad57c90c3b021f63a77cb56cde848e2e2dd20b487eec2f53101f634193786083f60b4d23a82301", "026cfe86116f161057deb240201d6b82ebd4f161e0200d63dc9aca65a1d6b38bb7"}, "a9147c8ab5ad7708b97ccb6b483d57aba48ee85214df87", 364);
+ // P2WPKH
+ CheckMaxWeightComputation("", {"3042021f0f8906f0394979d5b737134773e5b88bf036c7d63542301d600ab677ba5a59021f0e9fe07e62c113045fa1c1532e2914720e8854d189c4f5b8c88f57956b704401", "0359edba11ed1a0568094a6296a16c4d5ee4c8cfe2f5e2e6826871b5ecf8188f79"}, "00149961a78658030cc824af4c54fbf5294bec0cabdd", 272);
+ // P2WSH HTLC
+ CheckMaxWeightComputation("", {"3042021f5c4c29e6b686aae5b6d0751e90208592ea96d26bc81d78b0d3871a94a21fa8021f74dc2f971e438ccece8699c8fd15704c41df219ab37b63264f2147d15c34d801", "01", "6321024cf55e52ec8af7866617dc4e7ff8433758e98799906d80e066c6f32033f685f967029000b275210214827893e2dcbe4ad6c20bd743288edad21100404eb7f52ccd6062fd0e7808f268ac"}, "002089e84892873c679b1129edea246e484fd914c2601f776d4f2f4a001eb8059703", 318);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+} // namespace feebumper
+} // namespace wallet
diff --git a/src/wallet/test/fuzz/coinselection.cpp b/src/wallet/test/fuzz/coinselection.cpp
index 3465f2f331..90a328179e 100644
--- a/src/wallet/test/fuzz/coinselection.cpp
+++ b/src/wallet/test/fuzz/coinselection.cpp
@@ -58,6 +58,8 @@ FUZZ_TARGET(coinselection)
coin_params.m_subtract_fee_outputs = subtract_fee_outputs;
coin_params.m_long_term_feerate = long_term_fee_rate;
coin_params.m_effective_feerate = effective_fee_rate;
+ coin_params.change_output_size = fuzzed_data_provider.ConsumeIntegralInRange<int>(10, 1000);
+ coin_params.m_change_fee = effective_fee_rate.GetFee(coin_params.change_output_size);
// Create some coins
CAmount total_balance{0};
@@ -83,11 +85,11 @@ FUZZ_TARGET(coinselection)
const auto result_bnb = SelectCoinsBnB(group_pos, target, cost_of_change);
auto result_srd = SelectCoinsSRD(group_pos, target, fast_random_context);
- if (result_srd) result_srd->ComputeAndSetWaste(cost_of_change);
+ if (result_srd) result_srd->ComputeAndSetWaste(cost_of_change, cost_of_change, 0);
- CAmount change_target{GenerateChangeTarget(target, fast_random_context)};
+ CAmount change_target{GenerateChangeTarget(target, coin_params.m_change_fee, fast_random_context)};
auto result_knapsack = KnapsackSolver(group_all, target, change_target, fast_random_context);
- if (result_knapsack) result_knapsack->ComputeAndSetWaste(cost_of_change);
+ if (result_knapsack) result_knapsack->ComputeAndSetWaste(cost_of_change, cost_of_change, 0);
// If the total balance is sufficient for the target and we are not using
// effective values, Knapsack should always find a solution.
diff --git a/src/wallet/test/fuzz/notifications.cpp b/src/wallet/test/fuzz/notifications.cpp
index 9089c8ff46..5e9cd4001b 100644
--- a/src/wallet/test/fuzz/notifications.cpp
+++ b/src/wallet/test/fuzz/notifications.cpp
@@ -69,15 +69,13 @@ struct FuzzedWallet {
CScript GetScriptPubKey(FuzzedDataProvider& fuzzed_data_provider)
{
auto type{fuzzed_data_provider.PickValueInArray(OUTPUT_TYPES)};
- CTxDestination dest;
- bilingual_str error;
+ util::Result<CTxDestination> op_dest{util::Error{}};
if (fuzzed_data_provider.ConsumeBool()) {
- assert(wallet->GetNewDestination(type, "", dest, error));
+ op_dest = wallet->GetNewDestination(type, "");
} else {
- assert(wallet->GetNewChangeDestination(type, dest, error));
+ op_dest = wallet->GetNewChangeDestination(type);
}
- assert(error.empty());
- return GetScriptForDestination(dest);
+ return GetScriptForDestination(*Assert(op_dest));
}
};
@@ -138,8 +136,13 @@ FUZZ_TARGET_INIT(wallet_notifications, initialize_setup)
block.vtx.emplace_back(MakeTransactionRef(tx));
}
// Mine block
- a.wallet->blockConnected(block, chain.size());
- b.wallet->blockConnected(block, chain.size());
+ const uint256& hash = block.GetHash();
+ interfaces::BlockInfo info{hash};
+ info.prev_hash = &block.hashPrevBlock;
+ info.height = chain.size();
+ info.data = &block;
+ a.wallet->blockConnected(info);
+ b.wallet->blockConnected(info);
// Store the coins for the next block
Coins coins_new;
for (const auto& tx : block.vtx) {
@@ -155,8 +158,13 @@ FUZZ_TARGET_INIT(wallet_notifications, initialize_setup)
auto& [coins, block]{chain.back()};
if (block.vtx.empty()) return; // Can only disconnect if the block was submitted first
// Disconnect block
- a.wallet->blockDisconnected(block, chain.size() - 1);
- b.wallet->blockDisconnected(block, chain.size() - 1);
+ const uint256& hash = block.GetHash();
+ interfaces::BlockInfo info{hash};
+ info.prev_hash = &block.hashPrevBlock;
+ info.height = chain.size() - 1;
+ info.data = &block;
+ a.wallet->blockDisconnected(info);
+ b.wallet->blockDisconnected(info);
chain.pop_back();
});
auto& [coins, first_block]{chain.front()};
diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp
index dd5cd0af46..68146eb079 100644
--- a/src/wallet/test/ismine_tests.cpp
+++ b/src/wallet/test/ismine_tests.cpp
@@ -43,11 +43,13 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore does not have key
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has key
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// P2PK uncompressed
@@ -60,11 +62,13 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore does not have key
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has key
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// P2PKH compressed
@@ -77,11 +81,13 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore does not have key
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has key
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// P2PKH uncompressed
@@ -94,11 +100,13 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore does not have key
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has key
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// P2SH
@@ -113,16 +121,19 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore does not have redeemScript or key
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has redeemScript but no key
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has redeemScript and key
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// (P2PKH inside) P2SH inside P2SH (invalid)
@@ -141,6 +152,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// (P2PKH inside) P2SH inside P2WSH (invalid)
@@ -159,6 +171,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// P2WPKH inside P2WSH (invalid)
@@ -175,6 +188,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// (P2PKH inside) P2WSH inside P2WSH (invalid)
@@ -193,6 +207,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// P2WPKH compressed
@@ -208,6 +223,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// P2WPKH uncompressed
@@ -222,11 +238,13 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore has key, but no P2SH redeemScript
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has key and P2SH redeemScript
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// scriptPubKey multisig
@@ -240,24 +258,28 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore does not have any keys
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has 1/2 keys
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(uncompressedKey));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has 2/2 keys
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has 2/2 keys and the script
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// P2SH multisig
@@ -274,11 +296,13 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore has no redeemScript
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has redeemScript
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// P2WSH multisig with compressed keys
@@ -295,16 +319,19 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore has keys, but no witnessScript or P2SH redeemScript
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has keys and witnessScript, but no P2SH redeemScript
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has keys, witnessScript, P2SH redeemScript
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// P2WSH multisig with uncompressed key
@@ -321,16 +348,19 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore has keys, but no witnessScript or P2SH redeemScript
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has keys and witnessScript, but no P2SH redeemScript
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has keys, witnessScript, P2SH redeemScript
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(scriptPubKey));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// P2WSH multisig wrapped in P2SH
@@ -346,18 +376,21 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
// Keystore has no witnessScript, P2SH redeemScript, or keys
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has witnessScript and P2SH redeemScript, but no keys
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(redeemScript));
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddCScript(witnessScript));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
// Keystore has keys, witnessScript, P2SH redeemScript
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[0]));
BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->AddKey(keys[1]));
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 1);
}
// OP_RETURN
@@ -372,6 +405,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// witness unspendable
@@ -386,6 +420,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// witness unknown
@@ -400,6 +435,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
// Nonstandard
@@ -414,6 +450,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
result = keystore.GetLegacyScriptPubKeyMan()->IsMine(scriptPubKey);
BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(keystore.GetLegacyScriptPubKeyMan()->GetScriptPubKeys().count(scriptPubKey) == 0);
}
}
diff --git a/src/wallet/test/spend_tests.cpp b/src/wallet/test/spend_tests.cpp
index bdc148afb4..81a8883f85 100644
--- a/src/wallet/test/spend_tests.cpp
+++ b/src/wallet/test/spend_tests.cpp
@@ -18,7 +18,7 @@ BOOST_FIXTURE_TEST_SUITE(spend_tests, WalletTestingSetup)
BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- auto wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey);
+ auto wallet = CreateSyncedWallet(*m_node.chain, WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain()), m_args, coinbaseKey);
// Check that a subtract-from-recipient transaction slightly less than the
// coinbase input amount does not create a change output (because it would
@@ -28,19 +28,18 @@ BOOST_FIXTURE_TEST_CASE(SubtractFee, TestChain100Setup)
auto check_tx = [&wallet](CAmount leftover_input_amount) {
CRecipient recipient{GetScriptForRawPubKey({}), 50 * COIN - leftover_input_amount, true /* subtract fee */};
constexpr int RANDOM_CHANGE_POSITION = -1;
- bilingual_str error;
CCoinControl coin_control;
coin_control.m_feerate.emplace(10000);
coin_control.fOverrideFeeRate = true;
// We need to use a change type with high cost of change so that the leftover amount will be dropped to fee instead of added as a change output
coin_control.m_change_type = OutputType::LEGACY;
- FeeCalculation fee_calc;
- std::optional<CreatedTransactionResult> txr = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, error, coin_control, fee_calc);
- BOOST_CHECK(txr.has_value());
- BOOST_CHECK_EQUAL(txr->tx->vout.size(), 1);
- BOOST_CHECK_EQUAL(txr->tx->vout[0].nValue, recipient.nAmount + leftover_input_amount - txr->fee);
- BOOST_CHECK_GT(txr->fee, 0);
- return txr->fee;
+ auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, coin_control);
+ BOOST_CHECK(res);
+ const auto& txr = *res;
+ BOOST_CHECK_EQUAL(txr.tx->vout.size(), 1);
+ BOOST_CHECK_EQUAL(txr.tx->vout[0].nValue, recipient.nAmount + leftover_input_amount - txr.fee);
+ BOOST_CHECK_GT(txr.fee, 0);
+ return txr.fee;
};
// Send full input amount to recipient, check that only nonzero fee is
@@ -113,5 +112,50 @@ BOOST_FIXTURE_TEST_CASE(FillInputToWeightTest, BasicTestingSetup)
// Note: We don't test the next boundary because of memory allocation constraints.
}
+BOOST_FIXTURE_TEST_CASE(wallet_duplicated_preset_inputs_test, TestChain100Setup)
+{
+ // Verify that the wallet's Coin Selection process does not include pre-selected inputs twice in a transaction.
+
+ // Add 4 spendable UTXO, 50 BTC each, to the wallet (total balance 200 BTC)
+ for (int i = 0; i < 4; i++) CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+ auto wallet = CreateSyncedWallet(*m_node.chain, WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain()), m_args, coinbaseKey);
+
+ LOCK(wallet->cs_wallet);
+ auto available_coins = AvailableCoins(*wallet);
+ std::vector<COutput> coins = available_coins.All();
+ // Preselect the first 3 UTXO (150 BTC total)
+ std::set<COutPoint> preset_inputs = {coins[0].outpoint, coins[1].outpoint, coins[2].outpoint};
+
+ // Try to create a tx that spends more than what preset inputs + wallet selected inputs are covering for.
+ // The wallet can cover up to 200 BTC, and the tx target is 299 BTC.
+ std::vector<CRecipient> recipients = {{GetScriptForDestination(*Assert(wallet->GetNewDestination(OutputType::BECH32, "dummy"))),
+ /*nAmount=*/299 * COIN, /*fSubtractFeeFromAmount=*/true}};
+ CCoinControl coin_control;
+ coin_control.m_allow_other_inputs = true;
+ for (const auto& outpoint : preset_inputs) {
+ coin_control.Select(outpoint);
+ }
+
+ // Attempt to send 299 BTC from a wallet that only has 200 BTC. The wallet should exclude
+ // the preset inputs from the pool of available coins, realize that there is not enough
+ // money to fund the 299 BTC payment, and fail with "Insufficient funds".
+ //
+ // Even with SFFO, the wallet can only afford to send 200 BTC.
+ // If the wallet does not properly exclude preset inputs from the pool of available coins
+ // prior to coin selection, it may create a transaction that does not fund the full payment
+ // amount or, through SFFO, incorrectly reduce the recipient's amount by the difference
+ // between the original target and the wrongly counted inputs (in this case 99 BTC)
+ // so that the recipient's amount is no longer equal to the user's selected target of 299 BTC.
+
+ // First case, use 'subtract_fee_from_outputs=true'
+ util::Result<CreatedTransactionResult> res_tx = CreateTransaction(*wallet, recipients, /*change_pos*/-1, coin_control);
+ BOOST_CHECK(!res_tx.has_value());
+
+ // Second case, don't use 'subtract_fee_from_outputs'.
+ recipients[0].fSubtractFeeFromAmount = false;
+ res_tx = CreateTransaction(*wallet, recipients, /*change_pos*/-1, coin_control);
+ BOOST_CHECK(!res_tx.has_value());
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet
diff --git a/src/wallet/test/util.cpp b/src/wallet/test/util.cpp
index aa3121511d..ab72721f9d 100644
--- a/src/wallet/test/util.cpp
+++ b/src/wallet/test/util.cpp
@@ -38,7 +38,7 @@ std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cc
}
WalletRescanReserver reserver(*wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), 0 /* start_height */, {} /* max_height */, reserver, false /* update */);
+ CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
BOOST_CHECK_EQUAL(result.last_scanned_block, cchain.Tip()->GetBlockHash());
BOOST_CHECK_EQUAL(*result.last_scanned_height, cchain.Height());
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 0c03b2f4a2..60fdbde71b 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -4,7 +4,6 @@
#include <wallet/wallet.h>
-#include <any>
#include <future>
#include <memory>
#include <stdint.h>
@@ -13,7 +12,6 @@
#include <interfaces/chain.h>
#include <key_io.h>
#include <node/blockstorage.h>
-#include <node/context.h>
#include <policy/policy.h>
#include <rpc/server.h>
#include <test/util/logging.h>
@@ -55,9 +53,6 @@ static const std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
auto database = MakeWalletDatabase("", options, status, error);
auto wallet = CWallet::Create(context, "", std::move(database), options.create_flags, error, warnings);
NotifyWalletLoaded(context, wallet);
- if (context.chain) {
- wallet->postInitProcess();
- }
return wallet;
}
@@ -96,23 +91,24 @@ static void AddKey(CWallet& wallet, const CKey& key)
BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
{
// Cap last block file size, and mine new block in a new block file.
- CBlockIndex* oldTip = m_node.chainman->ActiveChain().Tip();
+ CBlockIndex* oldTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip());
WITH_LOCK(::cs_main, m_node.chainman->m_blockman.GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE);
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- CBlockIndex* newTip = m_node.chainman->ActiveChain().Tip();
+ CBlockIndex* newTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip());
// Verify ScanForWalletTransactions fails to read an unknown start block.
{
CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
+ LOCK(Assert(m_node.chainman)->GetMutex());
wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
}
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet.ScanForWalletTransactions({} /* start_block */, 0 /* start_height */, {} /* max_height */, reserver, false /* update */);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(/*start_block=*/{}, /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::FAILURE);
BOOST_CHECK(result.last_failed_block.IsNull());
BOOST_CHECK(result.last_scanned_block.IsNull());
@@ -123,21 +119,37 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions picks up transactions in both the old
// and new block files.
{
- CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", m_args, CreateMockWalletDatabase());
{
LOCK(wallet.cs_wallet);
+ LOCK(Assert(m_node.chainman)->GetMutex());
wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
}
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(wallet);
+ std::chrono::steady_clock::time_point fake_time;
+ reserver.setNow([&] { fake_time += 60s; return fake_time; });
reserver.reserve();
- CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), oldTip->nHeight, {} /* max_height */, reserver, false /* update */);
+
+ {
+ CBlockLocator locator;
+ BOOST_CHECK(!WalletBatch{wallet.GetDatabase()}.ReadBestBlock(locator));
+ BOOST_CHECK(locator.IsNull());
+ }
+
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(/*start_block=*/oldTip->GetBlockHash(), /*start_height=*/oldTip->nHeight, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/true);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
BOOST_CHECK(result.last_failed_block.IsNull());
BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
BOOST_CHECK_EQUAL(*result.last_scanned_height, newTip->nHeight);
BOOST_CHECK_EQUAL(GetBalance(wallet).m_mine_immature, 100 * COIN);
+
+ {
+ CBlockLocator locator;
+ BOOST_CHECK(WalletBatch{wallet.GetDatabase()}.ReadBestBlock(locator));
+ BOOST_CHECK(!locator.IsNull());
+ }
}
// Prune the older block file.
@@ -155,13 +167,14 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
+ LOCK(Assert(m_node.chainman)->GetMutex());
wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
}
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), oldTip->nHeight, {} /* max_height */, reserver, false /* update */);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(/*start_block=*/oldTip->GetBlockHash(), /*start_height=*/oldTip->nHeight, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::FAILURE);
BOOST_CHECK_EQUAL(result.last_failed_block, oldTip->GetBlockHash());
BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
@@ -182,13 +195,14 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
+ LOCK(Assert(m_node.chainman)->GetMutex());
wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet.SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
}
AddKey(wallet, coinbaseKey);
WalletRescanReserver reserver(wallet);
reserver.reserve();
- CWallet::ScanResult result = wallet.ScanForWalletTransactions(oldTip->GetBlockHash(), oldTip->nHeight, {} /* max_height */, reserver, false /* update */);
+ CWallet::ScanResult result = wallet.ScanForWalletTransactions(/*start_block=*/oldTip->GetBlockHash(), /*start_height=*/oldTip->nHeight, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::FAILURE);
BOOST_CHECK_EQUAL(result.last_failed_block, newTip->GetBlockHash());
BOOST_CHECK(result.last_scanned_block.IsNull());
@@ -200,10 +214,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
{
// Cap last block file size, and mine new block in a new block file.
- CBlockIndex* oldTip = m_node.chainman->ActiveChain().Tip();
+ CBlockIndex* oldTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip());
WITH_LOCK(::cs_main, m_node.chainman->m_blockman.GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE);
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- CBlockIndex* newTip = m_node.chainman->ActiveChain().Tip();
+ CBlockIndex* newTip = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip());
// Prune the older block file.
int file_number;
@@ -267,7 +281,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
{
// Create two blocks with same timestamp to verify that importwallet rescan
// will pick up both blocks, not just the first.
- const int64_t BLOCK_TIME = m_node.chainman->ActiveChain().Tip()->GetBlockTimeMax() + 5;
+ const int64_t BLOCK_TIME = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockTimeMax() + 5);
SetMockTime(BLOCK_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
@@ -292,6 +306,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
AddWallet(context, wallet);
+ LOCK(Assert(m_node.chainman)->GetMutex());
wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
}
JSONRPCRequest request;
@@ -317,6 +332,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
request.params.setArray();
request.params.push_back(backup_file);
AddWallet(context, wallet);
+ LOCK(Assert(m_node.chainman)->GetMutex());
wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
wallet::importwallet().HandleRequest(request);
RemoveWallet(context, wallet, /* load_on_start= */ std::nullopt);
@@ -340,9 +356,10 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
CWallet wallet(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase());
- CWalletTx wtx{m_coinbase_txns.back(), TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/0}};
LOCK(wallet.cs_wallet);
+ LOCK(Assert(m_node.chainman)->GetMutex());
+ CWalletTx wtx{m_coinbase_txns.back(), TxStateConfirmed{m_node.chainman->ActiveChain().Tip()->GetBlockHash(), m_node.chainman->ActiveChain().Height(), /*index=*/0}};
wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet.SetupDescriptorScriptPubKeyMans();
@@ -350,13 +367,13 @@ BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
// Call GetImmatureCredit() once before adding the key to the wallet to
// cache the current immature credit amount, which is 0.
- BOOST_CHECK_EQUAL(CachedTxGetImmatureCredit(wallet, wtx), 0);
+ BOOST_CHECK_EQUAL(CachedTxGetImmatureCredit(wallet, wtx, ISMINE_SPENDABLE), 0);
// Invalidate the cached value, add the key, and make sure a new immature
// credit amount is calculated.
wtx.MarkDirty();
AddKey(wallet, coinbaseKey);
- BOOST_CHECK_EQUAL(CachedTxGetImmatureCredit(wallet, wtx), 50*COIN);
+ BOOST_CHECK_EQUAL(CachedTxGetImmatureCredit(wallet, wtx, ISMINE_SPENDABLE), 50*COIN);
}
static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)
@@ -510,7 +527,7 @@ public:
ListCoinsTestingSetup()
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- wallet = CreateSyncedWallet(*m_node.chain, m_node.chainman->ActiveChain(), m_args, coinbaseKey);
+ wallet = CreateSyncedWallet(*m_node.chain, WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain()), m_args, coinbaseKey);
}
~ListCoinsTestingSetup()
@@ -521,14 +538,12 @@ public:
CWalletTx& AddTx(CRecipient recipient)
{
CTransactionRef tx;
- bilingual_str error;
CCoinControl dummy;
- FeeCalculation fee_calc_out;
{
constexpr int RANDOM_CHANGE_POSITION = -1;
- std::optional<CreatedTransactionResult> txr = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, error, dummy, fee_calc_out);
- BOOST_CHECK(txr.has_value());
- tx = txr->tx;
+ auto res = CreateTransaction(*wallet, {recipient}, RANDOM_CHANGE_POSITION, dummy);
+ BOOST_CHECK(res);
+ tx = res->tx;
}
wallet->CommitTransaction(tx, {}, {});
CMutableTransaction blocktx;
@@ -539,6 +554,7 @@ public:
CreateAndProcessBlock({CMutableTransaction(blocktx)}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
LOCK(wallet->cs_wallet);
+ LOCK(Assert(m_node.chainman)->GetMutex());
wallet->SetLastBlockProcessed(wallet->GetLastBlockHeight() + 1, m_node.chainman->ActiveChain().Tip()->GetBlockHash());
auto it = wallet->mapWallet.find(tx->GetHash());
BOOST_CHECK(it != wallet->mapWallet.end());
@@ -583,7 +599,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup)
// Lock both coins. Confirm number of available coins drops to 0.
{
LOCK(wallet->cs_wallet);
- BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).coins.size(), 2U);
+ BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).Size(), 2U);
}
for (const auto& group : list) {
for (const auto& coin : group.second) {
@@ -593,7 +609,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoinsTest, ListCoinsTestingSetup)
}
{
LOCK(wallet->cs_wallet);
- BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).coins.size(), 0U);
+ BOOST_CHECK_EQUAL(AvailableCoinsListUnspent(*wallet).Size(), 0U);
}
// Confirm ListCoins still returns same result as before, despite coins
// being locked.
@@ -614,9 +630,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
BOOST_CHECK(!wallet->TopUpKeyPool(1000));
- CTxDestination dest;
- bilingual_str error;
- BOOST_CHECK(!wallet->GetNewDestination(OutputType::BECH32, "", dest, error));
+ BOOST_CHECK(!wallet->GetNewDestination(OutputType::BECH32, ""));
}
{
const std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", m_args, CreateDummyWalletDatabase());
@@ -624,9 +638,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
- CTxDestination dest;
- bilingual_str error;
- BOOST_CHECK(!wallet->GetNewDestination(OutputType::BECH32, "", dest, error));
+ BOOST_CHECK(!wallet->GetNewDestination(OutputType::BECH32, ""));
}
}
@@ -761,6 +773,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
// being blocked
wallet = TestLoadWallet(context);
BOOST_CHECK(rescan_completed);
+ // AddToWallet events for block_tx and mempool_tx
BOOST_CHECK_EQUAL(addtx_count, 2);
{
LOCK(wallet->cs_wallet);
@@ -773,6 +786,8 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
// transactionAddedToMempool events are processed
promise.set_value();
SyncWithValidationInterfaceQueue();
+ // AddToWallet events for block_tx and mempool_tx events are counted a
+ // second time as the notification queue is processed
BOOST_CHECK_EQUAL(addtx_count, 4);
@@ -796,7 +811,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
SyncWithValidationInterfaceQueue();
});
wallet = TestLoadWallet(context);
- BOOST_CHECK_EQUAL(addtx_count, 4);
+ BOOST_CHECK_EQUAL(addtx_count, 2);
{
LOCK(wallet->cs_wallet);
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_tx.GetHash()), 1U);
@@ -836,21 +851,126 @@ BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
{
auto block_hash = block_tx.GetHash();
- auto prev_hash = m_coinbase_txns[0]->GetHash();
+ auto prev_tx = m_coinbase_txns[0];
LOCK(wallet->cs_wallet);
- BOOST_CHECK(wallet->HasWalletSpend(prev_hash));
+ BOOST_CHECK(wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 1u);
std::vector<uint256> vHashIn{ block_hash }, vHashOut;
BOOST_CHECK_EQUAL(wallet->ZapSelectTx(vHashIn, vHashOut), DBErrors::LOAD_OK);
- BOOST_CHECK(!wallet->HasWalletSpend(prev_hash));
+ BOOST_CHECK(!wallet->HasWalletSpend(prev_tx));
BOOST_CHECK_EQUAL(wallet->mapWallet.count(block_hash), 0u);
}
TestUnloadWallet(std::move(wallet));
}
+/** RAII class that provides access to a FailDatabase. Which fails if needed. */
+class FailBatch : public DatabaseBatch
+{
+private:
+ bool m_pass{true};
+ bool ReadKey(CDataStream&& key, CDataStream& value) override { return m_pass; }
+ bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return m_pass; }
+ bool EraseKey(CDataStream&& key) override { return m_pass; }
+ bool HasKey(CDataStream&& key) override { return m_pass; }
+
+public:
+ explicit FailBatch(bool pass) : m_pass(pass) {}
+ void Flush() override {}
+ void Close() override {}
+
+ bool StartCursor() override { return true; }
+ bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return false; }
+ void CloseCursor() override {}
+ bool TxnBegin() override { return false; }
+ bool TxnCommit() override { return false; }
+ bool TxnAbort() override { return false; }
+};
+
+/** A dummy WalletDatabase that does nothing, only fails if needed.**/
+class FailDatabase : public WalletDatabase
+{
+public:
+ bool m_pass{true}; // false when this db should fail
+
+ void Open() override {};
+ void AddRef() override {}
+ void RemoveRef() override {}
+ bool Rewrite(const char* pszSkip=nullptr) override { return true; }
+ bool Backup(const std::string& strDest) const override { return true; }
+ void Close() override {}
+ void Flush() override {}
+ bool PeriodicFlush() override { return true; }
+ void IncrementUpdateCounter() override { ++nUpdateCounter; }
+ void ReloadDbEnv() override {}
+ std::string Filename() override { return "faildb"; }
+ std::string Format() override { return "faildb"; }
+ std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override { return std::make_unique<FailBatch>(m_pass); }
+};
+
+/**
+ * Checks a wallet invalid state where the inputs (prev-txs) of a new arriving transaction are not marked dirty,
+ * while the transaction that spends them exist inside the in-memory wallet tx map (not stored on db due a db write failure).
+ */
+BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
+{
+ CWallet wallet(m_node.chain.get(), "", m_args, std::make_unique<FailDatabase>());
+ {
+ LOCK(wallet.cs_wallet);
+ wallet.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ wallet.SetupDescriptorScriptPubKeyMans();
+ }
+
+ // Add tx to wallet
+ const auto& op_dest = wallet.GetNewDestination(OutputType::BECH32M, "");
+ BOOST_ASSERT(op_dest);
+
+ CMutableTransaction mtx;
+ mtx.vout.push_back({COIN, GetScriptForDestination(*op_dest)});
+ mtx.vin.push_back(CTxIn(g_insecure_rand_ctx.rand256(), 0));
+ const auto& tx_id_to_spend = wallet.AddToWallet(MakeTransactionRef(mtx), TxStateInMempool{})->GetHash();
+
+ {
+ // Cache and verify available balance for the wtx
+ LOCK(wallet.cs_wallet);
+ const CWalletTx* wtx_to_spend = wallet.GetWalletTx(tx_id_to_spend);
+ BOOST_CHECK_EQUAL(CachedTxGetAvailableCredit(wallet, *wtx_to_spend), 1 * COIN);
+ }
+
+ // Now the good case:
+ // 1) Add a transaction that spends the previously created transaction
+ // 2) Verify that the available balance of this new tx and the old one is updated (prev tx is marked dirty)
+
+ mtx.vin.clear();
+ mtx.vin.push_back(CTxIn(tx_id_to_spend, 0));
+ wallet.transactionAddedToMempool(MakeTransactionRef(mtx), 0);
+ const uint256& good_tx_id = mtx.GetHash();
+
+ {
+ // Verify balance update for the new tx and the old one
+ LOCK(wallet.cs_wallet);
+ const CWalletTx* new_wtx = wallet.GetWalletTx(good_tx_id);
+ BOOST_CHECK_EQUAL(CachedTxGetAvailableCredit(wallet, *new_wtx), 1 * COIN);
+
+ // Now the old wtx
+ const CWalletTx* wtx_to_spend = wallet.GetWalletTx(tx_id_to_spend);
+ BOOST_CHECK_EQUAL(CachedTxGetAvailableCredit(wallet, *wtx_to_spend), 0 * COIN);
+ }
+
+ // Now the bad case:
+ // 1) Make db always fail
+ // 2) Try to add a transaction that spends the previously created transaction and
+ // verify that we are not moving forward if the wallet cannot store it
+ static_cast<FailDatabase&>(wallet.GetDatabase()).m_pass = false;
+ mtx.vin.clear();
+ mtx.vin.push_back(CTxIn(good_tx_id, 0));
+ BOOST_CHECK_EXCEPTION(wallet.transactionAddedToMempool(MakeTransactionRef(mtx), 0),
+ std::runtime_error,
+ HasReason("DB error adding transaction to wallet, write failed"));
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace wallet
diff --git a/src/wallet/test/walletload_tests.cpp b/src/wallet/test/walletload_tests.cpp
new file mode 100644
index 0000000000..f45b69a418
--- /dev/null
+++ b/src/wallet/test/walletload_tests.cpp
@@ -0,0 +1,54 @@
+// Copyright (c) 2022 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or https://www.opensource.org/licenses/mit-license.php.
+
+#include <wallet/wallet.h>
+#include <test/util/setup_common.h>
+
+#include <boost/test/unit_test.hpp>
+
+namespace wallet {
+
+BOOST_AUTO_TEST_SUITE(walletload_tests)
+
+class DummyDescriptor final : public Descriptor {
+private:
+ std::string desc;
+public:
+ explicit DummyDescriptor(const std::string& descriptor) : desc(descriptor) {};
+ ~DummyDescriptor() = default;
+
+ std::string ToString() const override { return desc; }
+ std::optional<OutputType> GetOutputType() const override { return OutputType::UNKNOWN; }
+
+ bool IsRange() const override { return false; }
+ bool IsSolvable() const override { return false; }
+ bool IsSingleType() const override { return true; }
+ bool ToPrivateString(const SigningProvider& provider, std::string& out) const override { return false; }
+ bool ToNormalizedString(const SigningProvider& provider, std::string& out, const DescriptorCache* cache = nullptr) const override { return false; }
+ bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, DescriptorCache* write_cache = nullptr) const override { return false; };
+ bool ExpandFromCache(int pos, const DescriptorCache& read_cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const override { return false; }
+ void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const override {}
+};
+
+BOOST_FIXTURE_TEST_CASE(wallet_load_unknown_descriptor, TestingSetup)
+{
+ std::unique_ptr<WalletDatabase> database = CreateMockWalletDatabase();
+ {
+ // Write unknown active descriptor
+ WalletBatch batch(*database, false);
+ std::string unknown_desc = "trx(tpubD6NzVbkrYhZ4Y4S7m6Y5s9GD8FqEMBy56AGphZXuagajudVZEnYyBahZMgHNCTJc2at82YX6s8JiL1Lohu5A3v1Ur76qguNH4QVQ7qYrBQx/86'/1'/0'/0/*)#8pn8tzdt";
+ WalletDescriptor wallet_descriptor(std::make_shared<DummyDescriptor>(unknown_desc), 0, 0, 0, 0);
+ BOOST_CHECK(batch.WriteDescriptor(uint256(), wallet_descriptor));
+ BOOST_CHECK(batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(OutputType::UNKNOWN), uint256(), false));
+ }
+
+ {
+ // Now try to load the wallet and verify the error.
+ const std::shared_ptr<CWallet> wallet(new CWallet(m_node.chain.get(), "", m_args, std::move(database)));
+ BOOST_CHECK_EQUAL(wallet->LoadWallet(), DBErrors::UNKNOWN_DESCRIPTOR);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+} // namespace wallet
diff --git a/src/wallet/transaction.h b/src/wallet/transaction.h
index 271d698e56..27983e356d 100644
--- a/src/wallet/transaction.h
+++ b/src/wallet/transaction.h
@@ -305,6 +305,13 @@ public:
CWalletTx(CWalletTx const &) = delete;
void operator=(CWalletTx const &x) = delete;
};
+
+struct WalletTxOrderComparator {
+ bool operator()(const CWalletTx* a, const CWalletTx* b) const
+ {
+ return a->nOrderPos < b->nOrderPos;
+ }
+};
} // namespace wallet
#endif // BITCOIN_WALLET_TRANSACTION_H
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index d0b093bbb7..36fe32e54d 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -21,6 +21,7 @@
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <psbt.h>
+#include <random.h>
#include <script/descriptor.h>
#include <script/script.h>
#include <script/signingprovider.h>
@@ -149,6 +150,13 @@ std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context)
return context.wallets;
}
+std::shared_ptr<CWallet> GetDefaultWallet(WalletContext& context, size_t& count)
+{
+ LOCK(context.wallets_mutex);
+ count = context.wallets.size();
+ return count == 1 ? context.wallets[0] : nullptr;
+}
+
std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name)
{
LOCK(context.wallets_mutex);
@@ -379,25 +387,31 @@ std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& b
ReadDatabaseArgs(*context.args, options);
options.require_existing = true;
- if (!fs::exists(backup_file)) {
- error = Untranslated("Backup file does not exist");
- status = DatabaseStatus::FAILED_INVALID_BACKUP_FILE;
- return nullptr;
- }
-
const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name));
+ auto wallet_file = wallet_path / "wallet.dat";
+ std::shared_ptr<CWallet> wallet;
- if (fs::exists(wallet_path) || !TryCreateDirectories(wallet_path)) {
- error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(wallet_path)));
- status = DatabaseStatus::FAILED_ALREADY_EXISTS;
- return nullptr;
- }
+ try {
+ if (!fs::exists(backup_file)) {
+ error = Untranslated("Backup file does not exist");
+ status = DatabaseStatus::FAILED_INVALID_BACKUP_FILE;
+ return nullptr;
+ }
- auto wallet_file = wallet_path / "wallet.dat";
- fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
+ if (fs::exists(wallet_path) || !TryCreateDirectories(wallet_path)) {
+ error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(wallet_path)));
+ status = DatabaseStatus::FAILED_ALREADY_EXISTS;
+ return nullptr;
+ }
- auto wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
+ fs::copy_file(backup_file, wallet_file, fs::copy_options::none);
+ wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
+ } catch (const std::exception& e) {
+ assert(!wallet);
+ if (!error.empty()) error += Untranslated("\n");
+ error += strprintf(Untranslated("Unexpected exception: %s"), e.what());
+ }
if (!wallet) {
fs::remove(wallet_file);
fs::remove(wallet_path);
@@ -414,7 +428,7 @@ std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& b
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
{
AssertLockHeld(cs_wallet);
- std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
+ const auto it = mapWallet.find(hash);
if (it == mapWallet.end())
return nullptr;
return &(it->second);
@@ -535,6 +549,7 @@ void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in)
LOCK(cs_wallet);
if (nWalletVersion >= nVersion)
return;
+ WalletLogPrintf("Setting minversion to %d\n", nVersion);
nWalletVersion = nVersion;
{
@@ -551,7 +566,7 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
std::set<uint256> result;
AssertLockHeld(cs_wallet);
- std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
+ const auto it = mapWallet.find(txid);
if (it == mapWallet.end())
return result;
const CWalletTx& wtx = it->second;
@@ -569,11 +584,17 @@ std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
return result;
}
-bool CWallet::HasWalletSpend(const uint256& txid) const
+bool CWallet::HasWalletSpend(const CTransactionRef& tx) const
{
AssertLockHeld(cs_wallet);
- auto iter = mapTxSpends.lower_bound(COutPoint(txid, 0));
- return (iter != mapTxSpends.end() && iter->first.hash == txid);
+ const uint256& txid = tx->GetHash();
+ for (unsigned int i = 0; i < tx->vout.size(); ++i) {
+ auto iter = mapTxSpends.find(COutPoint(txid, i));
+ if (iter != mapTxSpends.end()) {
+ return true;
+ }
+ }
+ return false;
}
void CWallet::Flush()
@@ -636,7 +657,7 @@ bool CWallet::IsSpent(const COutPoint& outpoint) const
for (TxSpends::const_iterator it = range.first; it != range.second; ++it) {
const uint256& wtxid = it->second;
- std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
+ const auto mit = mapWallet.find(wtxid);
if (mit != mapWallet.end()) {
int depth = GetTxDepthInMainChain(mit->second);
if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
@@ -868,7 +889,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
wtx.mapValue["replaced_by_txid"] = newHash.ToString();
- // Refresh mempool status without waiting for transactionRemovedFromMempool
+ // Refresh mempool status without waiting for transactionRemovedFromMempool or transactionAddedToMempool
RefreshMempoolStatus(wtx, chain());
WalletBatch batch(GetDatabase());
@@ -1130,7 +1151,13 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const SyncTxS
// Block disconnection override an abandoned tx as unconfirmed
// which means user may have to call abandontransaction again
TxState tx_state = std::visit([](auto&& s) -> TxState { return s; }, state);
- return AddToWallet(MakeTransactionRef(tx), tx_state, /*update_wtx=*/nullptr, /*fFlushOnClose=*/false, rescanning_old_block);
+ CWalletTx* wtx = AddToWallet(MakeTransactionRef(tx), tx_state, /*update_wtx=*/nullptr, /*fFlushOnClose=*/false, rescanning_old_block);
+ if (!wtx) {
+ // Can only be nullptr if there was a db write error (missing db, read-only db or a db engine internal writing error).
+ // As we only store arriving transaction in this process, and we don't want an inconsistent state, let's throw an error.
+ throw std::runtime_error("DB error adding transaction to wallet, write failed");
+ }
+ return true;
}
}
return false;
@@ -1191,12 +1218,13 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
batch.WriteTx(wtx);
NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
// Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
- TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
- while (iter != mapTxSpends.end() && iter->first.hash == now) {
- if (!done.count(iter->second)) {
- todo.insert(iter->second);
+ for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
+ std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
+ for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
+ if (!done.count(iter->second)) {
+ todo.insert(iter->second);
+ }
}
- iter++;
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
@@ -1242,12 +1270,13 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
wtx.MarkDirty();
batch.WriteTx(wtx);
// Iterate over all its outputs, and mark transactions in the wallet that spend them conflicted too
- TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
- while (iter != mapTxSpends.end() && iter->first.hash == now) {
- if (!done.count(iter->second)) {
- todo.insert(iter->second);
- }
- iter++;
+ for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
+ std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(now, i));
+ for (TxSpends::const_iterator iter = range.first; iter != range.second; ++iter) {
+ if (!done.count(iter->second)) {
+ todo.insert(iter->second);
+ }
+ }
}
// If a transaction changes 'conflicted' state, that changes the balance
// available of the outputs it spends. So force those to be recomputed
@@ -1314,30 +1343,31 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe
}
}
-void CWallet::blockConnected(const CBlock& block, int height)
+void CWallet::blockConnected(const interfaces::BlockInfo& block)
{
- const uint256& block_hash = block.GetHash();
+ assert(block.data);
LOCK(cs_wallet);
- m_last_block_processed_height = height;
- m_last_block_processed = block_hash;
- for (size_t index = 0; index < block.vtx.size(); index++) {
- SyncTransaction(block.vtx[index], TxStateConfirmed{block_hash, height, static_cast<int>(index)});
- transactionRemovedFromMempool(block.vtx[index], MemPoolRemovalReason::BLOCK, 0 /* mempool_sequence */);
+ m_last_block_processed_height = block.height;
+ m_last_block_processed = block.hash;
+ for (size_t index = 0; index < block.data->vtx.size(); index++) {
+ SyncTransaction(block.data->vtx[index], TxStateConfirmed{block.hash, block.height, static_cast<int>(index)});
+ transactionRemovedFromMempool(block.data->vtx[index], MemPoolRemovalReason::BLOCK, 0 /* mempool_sequence */);
}
}
-void CWallet::blockDisconnected(const CBlock& block, int height)
+void CWallet::blockDisconnected(const interfaces::BlockInfo& block)
{
+ assert(block.data);
LOCK(cs_wallet);
// At block disconnection, this will change an abandoned transaction to
// be unconfirmed, whether or not the transaction is added back to the mempool.
// User may have to call abandontransaction again. It may be addressed in the
// future with a stickier abandoned state or even removing abandontransaction call.
- m_last_block_processed_height = height - 1;
- m_last_block_processed = block.hashPrevBlock;
- for (const CTransactionRef& ptx : block.vtx) {
+ m_last_block_processed_height = block.height - 1;
+ m_last_block_processed = *Assert(block.prev_hash);
+ for (const CTransactionRef& ptx : Assert(block.data)->vtx) {
SyncTransaction(ptx, TxStateInactive{});
}
}
@@ -1363,7 +1393,7 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
{
{
LOCK(cs_wallet);
- std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
+ const auto mi = mapWallet.find(txin.prevout.hash);
if (mi != mapWallet.end())
{
const CWalletTx& prev = (*mi).second;
@@ -1406,6 +1436,19 @@ bool CWallet::IsMine(const CTransaction& tx) const
return false;
}
+isminetype CWallet::IsMine(const COutPoint& outpoint) const
+{
+ AssertLockHeld(cs_wallet);
+ auto wtx = GetWalletTx(outpoint.hash);
+ if (!wtx) {
+ return ISMINE_NO;
+ }
+ if (outpoint.n >= wtx->tx->vout.size()) {
+ return ISMINE_NO;
+ }
+ return IsMine(wtx->tx->vout[outpoint.n]);
+}
+
bool CWallet::IsFromMe(const CTransaction& tx) const
{
return (GetDebit(tx, ISMINE_ALL) > 0);
@@ -1491,26 +1534,33 @@ bool CWallet::LoadWalletFlags(uint64_t flags)
return true;
}
-bool CWallet::AddWalletFlags(uint64_t flags)
+void CWallet::InitWalletFlags(uint64_t flags)
{
LOCK(cs_wallet);
+
// We should never be writing unknown non-tolerable wallet flags
assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
+ // This should only be used once, when creating a new wallet - so current flags are expected to be blank
+ assert(m_wallet_flags == 0);
+
if (!WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
}
- return LoadWalletFlags(flags);
+ if (!LoadWalletFlags(flags)) assert(false);
}
// Helper for producing a max-sized low-S low-R signature (eg 71 bytes)
-// or a max-sized low-S signature (e.g. 72 bytes) if use_max_sig is true
-bool DummySignInput(const SigningProvider& provider, CTxIn &tx_in, const CTxOut &txout, bool use_max_sig)
+// or a max-sized low-S signature (e.g. 72 bytes) depending on coin_control
+bool DummySignInput(const SigningProvider& provider, CTxIn &tx_in, const CTxOut &txout, const CCoinControl* coin_control)
{
// Fill in dummy signatures for fee calculation.
const CScript& scriptPubKey = txout.scriptPubKey;
SignatureData sigdata;
+ // Use max sig if watch only inputs were used or if this particular input is an external input
+ // to ensure a sufficient fee is attained for the requested feerate.
+ const bool use_max_sig = coin_control && (coin_control->fAllowWatchOnly || coin_control->IsExternalSelected(tx_in.prevout));
if (!ProduceSignature(provider, use_max_sig ? DUMMY_MAXIMUM_SIGNATURE_CREATOR : DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigdata)) {
return false;
}
@@ -1577,12 +1627,9 @@ bool CWallet::DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut>
nIn++;
continue;
}
- // Use max sig if watch only inputs were used or if this particular input is an external input
- // to ensure a sufficient fee is attained for the requested feerate.
- const bool use_max_sig = coin_control && (coin_control->fAllowWatchOnly || coin_control->IsExternalSelected(txin.prevout));
const std::unique_ptr<SigningProvider> provider = GetSolvingProvider(txout.scriptPubKey);
- if (!provider || !DummySignInput(*provider, txin, txout, use_max_sig)) {
- if (!coin_control || !DummySignInput(coin_control->m_external_provider, txin, txout, use_max_sig)) {
+ if (!provider || !DummySignInput(*provider, txin, txout, coin_control)) {
+ if (!coin_control || !DummySignInput(coin_control->m_external_provider, txin, txout, coin_control)) {
return false;
}
}
@@ -1665,7 +1712,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
if (start) {
// TODO: this should take into account failure by ScanResult::USER_ABORT
- ScanResult result = ScanForWalletTransactions(start_block, start_height, {} /* max_height */, reserver, update);
+ ScanResult result = ScanForWalletTransactions(start_block, start_height, /*max_height=*/{}, reserver, /*fUpdate=*/update, /*save_progress=*/false);
if (result.status == ScanResult::FAILURE) {
int64_t time_max;
CHECK_NONFATAL(chain().findBlock(result.last_failed_block, FoundBlock().maxTime(time_max)));
@@ -1678,7 +1725,8 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
/**
* Scan the block chain (starting in start_block) for transactions
* from or to us. If fUpdate is true, found transactions that already
- * exist in the wallet will be updated.
+ * exist in the wallet will be updated. If max_height is not set, the
+ * mempool will be scanned as well.
*
* @param[in] start_block Scan starting block. If block is not on the active
* chain, the scan will return SUCCESS immediately.
@@ -1696,12 +1744,11 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
* the main chain after to the addition of any new keys you want to detect
* transactions for.
*/
-CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate)
+CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate, const bool save_progress)
{
- using Clock = std::chrono::steady_clock;
- constexpr auto LOG_INTERVAL{60s};
- auto current_time{Clock::now()};
- auto start_time{Clock::now()};
+ constexpr auto INTERVAL_TIME{60s};
+ auto current_time{reserver.now()};
+ auto start_time{reserver.now()};
assert(reserver.isReserved());
@@ -1728,8 +1775,10 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
if (block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
}
- if (Clock::now() >= current_time + LOG_INTERVAL) {
- current_time = Clock::now();
+
+ bool next_interval = reserver.now() >= current_time + INTERVAL_TIME;
+ if (next_interval) {
+ current_time = reserver.now();
WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
}
@@ -1759,6 +1808,16 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
// scan succeeded, record block as most recent successfully scanned
result.last_scanned_block = block_hash;
result.last_scanned_height = block_height;
+
+ if (save_progress && next_interval) {
+ CBlockLocator loc = m_chain->getActiveChainLocator(block_hash);
+
+ if (!loc.IsNull()) {
+ WalletLogPrintf("Saving scan progress %d.\n", block_height);
+ WalletBatch batch(GetDatabase());
+ batch.WriteBestBlock(loc);
+ }
+ }
} else {
// could not scan block, keep scanning but record this block as the most recent failure
result.last_failed_block = block_hash;
@@ -1788,6 +1847,10 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
}
}
}
+ if (!max_height) {
+ WalletLogPrintf("Scanning current mempool transactions.\n");
+ WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
+ }
ShowProgress(strprintf("%s " + _("Rescanning…").translated, GetDisplayName()), 100); // hide progress dialog in GUI
if (block_height && fAbortRescan) {
WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", block_height, progress_current);
@@ -1796,40 +1859,11 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", block_height, progress_current);
result.status = ScanResult::USER_ABORT;
} else {
- auto duration_milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - start_time);
- WalletLogPrintf("Rescan completed in %15dms\n", duration_milliseconds.count());
+ WalletLogPrintf("Rescan completed in %15dms\n", Ticks<std::chrono::milliseconds>(reserver.now() - start_time));
}
return result;
}
-void CWallet::ReacceptWalletTransactions()
-{
- // If transactions aren't being broadcasted, don't let them into local mempool either
- if (!fBroadcastTransactions)
- return;
- std::map<int64_t, CWalletTx*> mapSorted;
-
- // Sort pending wallet transactions based on their initial wallet insertion order
- for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
- const uint256& wtxid = item.first;
- CWalletTx& wtx = item.second;
- assert(wtx.GetHash() == wtxid);
-
- int nDepth = GetTxDepthInMainChain(wtx);
-
- if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
- mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
- }
- }
-
- // Try to add wallet transactions to memory pool
- for (const std::pair<const int64_t, CWalletTx*>& item : mapSorted) {
- CWalletTx& wtx = *(item.second);
- std::string unused_err_string;
- SubmitTxMemoryPoolAndRelay(wtx, unused_err_string, false);
- }
-}
-
bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const
{
AssertLockHeld(cs_wallet);
@@ -1870,43 +1904,76 @@ std::set<uint256> CWallet::GetTxConflicts(const CWalletTx& wtx) const
return result;
}
-// Rebroadcast transactions from the wallet. We do this on a random timer
-// to slightly obfuscate which transactions come from our wallet.
+bool CWallet::ShouldResend() const
+{
+ // Don't attempt to resubmit if the wallet is configured to not broadcast
+ if (!fBroadcastTransactions) return false;
+
+ // During reindex, importing and IBD, old wallet transactions become
+ // unconfirmed. Don't resend them as that would spam other nodes.
+ // We only allow forcing mempool submission when not relaying to avoid this spam.
+ if (!chain().isReadyToBroadcast()) return false;
+
+ // Do this infrequently and randomly to avoid giving away
+ // that these are our transactions.
+ if (GetTime() < m_next_resend) return false;
+
+ return true;
+}
+
+int64_t CWallet::GetDefaultNextResend() { return GetTime() + (12 * 60 * 60) + GetRand(24 * 60 * 60); }
+
+// Resubmit transactions from the wallet to the mempool, optionally asking the
+// mempool to relay them. On startup, we will do this for all unconfirmed
+// transactions but will not ask the mempool to relay them. We do this on startup
+// to ensure that our own mempool is aware of our transactions. There
+// is a privacy side effect here as not broadcasting on startup also means that we won't
+// inform the world of our wallet's state, particularly if the wallet (or node) is not
+// yet synced.
+//
+// Otherwise this function is called periodically in order to relay our unconfirmed txs.
+// We do this on a random timer to slightly obfuscate which transactions
+// come from our wallet.
//
-// Ideally, we'd only resend transactions that we think should have been
+// TODO: Ideally, we'd only resend transactions that we think should have been
// mined in the most recent block. Any transaction that wasn't in the top
// blockweight of transactions in the mempool shouldn't have been mined,
// and so is probably just sitting in the mempool waiting to be confirmed.
// Rebroadcasting does nothing to speed up confirmation and only damages
// privacy.
-void CWallet::ResendWalletTransactions()
+//
+// The `force` option results in all unconfirmed transactions being submitted to
+// the mempool. This does not necessarily result in those transactions being relayed,
+// that depends on the `relay` option. Periodic rebroadcast uses the pattern
+// relay=true force=false, while loading into the mempool
+// (on start, or after import) uses relay=false force=true.
+void CWallet::ResubmitWalletTransactions(bool relay, bool force)
{
- // During reindex, importing and IBD, old wallet transactions become
- // unconfirmed. Don't resend them as that would spam other nodes.
- if (!chain().isReadyToBroadcast()) return;
-
- // Do this infrequently and randomly to avoid giving away
- // that these are our transactions.
- if (GetTime() < nNextResend || !fBroadcastTransactions) return;
- bool fFirst = (nNextResend == 0);
- // resend 12-36 hours from now, ~1 day on average.
- nNextResend = GetTime() + (12 * 60 * 60) + GetRand(24 * 60 * 60);
- if (fFirst) return;
+ // Don't attempt to resubmit if the wallet is configured to not broadcast,
+ // even if forcing.
+ if (!fBroadcastTransactions) return;
int submitted_tx_count = 0;
{ // cs_wallet scope
LOCK(cs_wallet);
- // Relay transactions
- for (std::pair<const uint256, CWalletTx>& item : mapWallet) {
- CWalletTx& wtx = item.second;
- // Attempt to rebroadcast all txes more than 5 minutes older than
- // the last block. SubmitTxMemoryPoolAndRelay() will not rebroadcast
- // any confirmed or conflicting txs.
- if (wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
+ // First filter for the transactions we want to rebroadcast.
+ // We use a set with WalletTxOrderComparator so that rebroadcasting occurs in insertion order
+ std::set<CWalletTx*, WalletTxOrderComparator> to_submit;
+ for (auto& [txid, wtx] : mapWallet) {
+ // Only rebroadcast unconfirmed txs
+ if (!wtx.isUnconfirmed()) continue;
+
+ // attempt to rebroadcast all txes more than 5 minutes older than
+ // the last block, or all txs if forcing.
+ if (!force && wtx.nTimeReceived > m_best_block_time - 5 * 60) continue;
+ to_submit.insert(&wtx);
+ }
+ // Now try submitting the transactions to the memory pool and (optionally) relay them.
+ for (auto wtx : to_submit) {
std::string unused_err_string;
- if (SubmitTxMemoryPoolAndRelay(wtx, unused_err_string, true)) ++submitted_tx_count;
+ if (SubmitTxMemoryPoolAndRelay(*wtx, unused_err_string, relay)) ++submitted_tx_count;
}
} // cs_wallet
@@ -1920,7 +1987,9 @@ void CWallet::ResendWalletTransactions()
void MaybeResendWalletTxs(WalletContext& context)
{
for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) {
- pwallet->ResendWalletTransactions();
+ if (!pwallet->ShouldResend()) continue;
+ pwallet->ResubmitWalletTransactions(/*relay=*/true, /*force=*/false);
+ pwallet->SetNextResend();
}
}
@@ -1937,7 +2006,7 @@ bool CWallet::SignTransaction(CMutableTransaction& tx) const
// Build coins map
std::map<COutPoint, Coin> coins;
for (auto& input : tx.vin) {
- std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
+ const auto mi = mapWallet.find(input.prevout.hash);
if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
return false;
}
@@ -1969,7 +2038,6 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
if (n_signed) {
*n_signed = 0;
}
- const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
LOCK(cs_wallet);
// Get all of the previous transactions
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
@@ -1993,6 +2061,8 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
}
}
+ const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
+
// Fill in information from ScriptPubKeyMans
for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
int n_signed_this_spkm = 0;
@@ -2006,6 +2076,35 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
}
}
+ // Only drop non_witness_utxos if sighash_type != SIGHASH_ANYONECANPAY
+ if ((sighash_type & 0x80) != SIGHASH_ANYONECANPAY) {
+ // Figure out if any non_witness_utxos should be dropped
+ std::vector<unsigned int> to_drop;
+ for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
+ const auto& input = psbtx.inputs.at(i);
+ int wit_ver;
+ std::vector<unsigned char> wit_prog;
+ if (input.witness_utxo.IsNull() || !input.witness_utxo.scriptPubKey.IsWitnessProgram(wit_ver, wit_prog)) {
+ // There's a non-segwit input or Segwit v0, so we cannot drop any witness_utxos
+ to_drop.clear();
+ break;
+ }
+ if (wit_ver == 0) {
+ // Segwit v0, so we cannot drop any non_witness_utxos
+ to_drop.clear();
+ break;
+ }
+ if (input.non_witness_utxo) {
+ to_drop.push_back(i);
+ }
+ }
+
+ // Drop the non_witness_utxos that we can drop
+ for (unsigned int i : to_drop) {
+ psbtx.inputs.at(i).non_witness_utxo = nullptr;
+ }
+ }
+
// Complete if every input is now signed
complete = true;
for (const auto& input : psbtx.inputs) {
@@ -2021,6 +2120,7 @@ SigningResult CWallet::SignMessage(const std::string& message, const PKHash& pkh
CScript script_pub_key = GetScriptForDestination(pkhash);
for (const auto& spk_man_pair : m_spk_managers) {
if (spk_man_pair.second->CanProvide(script_pub_key, sigdata)) {
+ LOCK(cs_wallet); // DescriptorScriptPubKeyMan calls IsLocked which can lock cs_wallet in a deadlocking order
return spk_man_pair.second->SignMessage(message, pkhash, str_sig);
}
}
@@ -2278,37 +2378,32 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
return res;
}
-bool CWallet::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, bilingual_str& error)
+util::Result<CTxDestination> CWallet::GetNewDestination(const OutputType type, const std::string label)
{
LOCK(cs_wallet);
- error.clear();
- bool result = false;
auto spk_man = GetScriptPubKeyMan(type, false /* internal */);
- if (spk_man) {
- spk_man->TopUp();
- result = spk_man->GetNewDestination(type, dest, error);
- } else {
- error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type));
+ if (!spk_man) {
+ return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
}
- if (result) {
- SetAddressBook(dest, label, "receive");
+
+ spk_man->TopUp();
+ auto op_dest = spk_man->GetNewDestination(type);
+ if (op_dest) {
+ SetAddressBook(*op_dest, label, "receive");
}
- return result;
+ return op_dest;
}
-bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& dest, bilingual_str& error)
+util::Result<CTxDestination> CWallet::GetNewChangeDestination(const OutputType type)
{
LOCK(cs_wallet);
- error.clear();
ReserveDestination reservedest(this, type);
- if (!reservedest.GetReservedDestination(dest, true, error)) {
- return false;
- }
+ auto op_dest = reservedest.GetReservedDestination(true);
+ if (op_dest) reservedest.KeepDestination();
- reservedest.KeepDestination();
- return true;
+ return op_dest;
}
std::optional<int64_t> CWallet::GetOldestKeyPoolTime() const
@@ -2339,42 +2434,63 @@ void CWallet::MarkDestinationsDirty(const std::set<CTxDestination>& destinations
}
}
-std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) const
+void CWallet::ForEachAddrBookEntry(const ListAddrBookFunc& func) const
{
AssertLockHeld(cs_wallet);
- std::set<CTxDestination> result;
- for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book)
- {
- if (item.second.IsChange()) continue;
- const CTxDestination& address = item.first;
- const std::string& strName = item.second.GetLabel();
- if (strName == label)
- result.insert(address);
+ for (const std::pair<const CTxDestination, CAddressBookData>& item : m_address_book) {
+ const auto& entry = item.second;
+ func(item.first, entry.GetLabel(), entry.purpose, entry.IsChange());
}
+}
+
+std::vector<CTxDestination> CWallet::ListAddrBookAddresses(const std::optional<AddrBookFilter>& _filter) const
+{
+ AssertLockHeld(cs_wallet);
+ std::vector<CTxDestination> result;
+ AddrBookFilter filter = _filter ? *_filter : AddrBookFilter();
+ ForEachAddrBookEntry([&result, &filter](const CTxDestination& dest, const std::string& label, const std::string& purpose, bool is_change) {
+ // Filter by change
+ if (filter.ignore_change && is_change) return;
+ // Filter by label
+ if (filter.m_op_label && *filter.m_op_label != label) return;
+ // All good
+ result.emplace_back(dest);
+ });
return result;
}
-bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal, bilingual_str& error)
+std::set<std::string> CWallet::ListAddrBookLabels(const std::string& purpose) const
+{
+ AssertLockHeld(cs_wallet);
+ std::set<std::string> label_set;
+ ForEachAddrBookEntry([&](const CTxDestination& _dest, const std::string& _label,
+ const std::string& _purpose, bool _is_change) {
+ if (_is_change) return;
+ if (purpose.empty() || _purpose == purpose) {
+ label_set.insert(_label);
+ }
+ });
+ return label_set;
+}
+
+util::Result<CTxDestination> ReserveDestination::GetReservedDestination(bool internal)
{
m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
if (!m_spk_man) {
- error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type));
- return false;
+ return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
}
-
if (nIndex == -1)
{
m_spk_man->TopUp();
CKeyPool keypool;
- if (!m_spk_man->GetReservedDestination(type, internal, address, nIndex, keypool, error)) {
- return false;
- }
+ auto op_address = m_spk_man->GetReservedDestination(type, internal, nIndex, keypool);
+ if (!op_address) return op_address;
+ address = *op_address;
fInternal = keypool.fInternal;
}
- dest = address;
- return true;
+ return address;
}
void ReserveDestination::KeepDestination()
@@ -2687,7 +2803,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
ArgsManager& args = *Assert(context.args);
const std::string& walletFile = database->Filename();
- int64_t nStart = GetTimeMillis();
+ const auto start{SteadyClock::now()};
// TODO: Can't use std::make_shared because we need a custom deleter but
// should be possible to use std::allocate_shared.
const std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, args, std::move(database)), ReleaseWallet);
@@ -2720,8 +2836,12 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
warnings.push_back(strprintf(_("Error reading %s! Transaction data may be missing or incorrect."
" Rescanning wallet."), walletFile));
rescan_required = true;
- }
- else {
+ } else if (nLoadWalletRet == DBErrors::UNKNOWN_DESCRIPTOR) {
+ error = strprintf(_("Unrecognized descriptor found. Loading wallet %s\n\n"
+ "The wallet might had been created on a newer version.\n"
+ "Please try running the latest software version.\n"), walletFile);
+ return nullptr;
+ } else {
error = strprintf(_("Error loading %s"), walletFile);
return nullptr;
}
@@ -2736,7 +2856,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
// ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
walletInstance->SetMinVersion(FEATURE_LATEST);
- walletInstance->AddWalletFlags(wallet_creation_flags);
+ walletInstance->InitWalletFlags(wallet_creation_flags);
// Only create LegacyScriptPubKeyMan when not descriptor wallet
if (!walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
@@ -2904,7 +3024,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
walletInstance->m_spend_zero_conf_change = args.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
walletInstance->m_signal_rbf = args.GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
- walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", GetTimeMillis() - nStart);
+ walletInstance->WalletLogPrintf("Wallet completed loading in %15dms\n", Ticks<std::chrono::milliseconds>(SteadyClock::now() - start));
// Try to top up keypool. No-op if the wallet is locked.
walletInstance->TopUpKeyPool();
@@ -2982,20 +3102,31 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
if (tip_height && *tip_height != rescan_height)
{
- if (chain.havePruned()) {
+ // Technically we could execute the code below in any case, but performing the
+ // `while` loop below can make startup very slow, so only check blocks on disk
+ // if necessary.
+ if (chain.havePruned() || chain.hasAssumedValidChain()) {
int block_height = *tip_height;
while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
--block_height;
}
if (rescan_height != block_height) {
- // We can't rescan beyond non-pruned blocks, stop and throw an error.
+ // We can't rescan beyond blocks we don't have data for, stop and throw an error.
// This might happen if a user uses an old wallet within a pruned node
// or if they ran -disablewallet for a longer time, then decided to re-enable
// Exit early and print an error.
+ // It also may happen if an assumed-valid chain is in use and therefore not
+ // all block data is available.
// If a block is pruned after this check, we will load the wallet,
// but fail the rescan with a generic error.
- error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
+
+ error = chain.hasAssumedValidChain() ?
+ _(
+ "Assumed-valid: last wallet synchronisation goes beyond "
+ "available block data. You need to wait for the background "
+ "validation chain to download more blocks.") :
+ _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
return false;
}
}
@@ -3016,7 +3147,7 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
{
WalletRescanReserver reserver(*walletInstance);
- if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, {} /* max height */, reserver, true /* update */).status)) {
+ if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, /*max_height=*/{}, reserver, /*fUpdate=*/true, /*save_progress=*/true).status)) {
error = _("Failed to rescan the wallet during initialization");
return false;
}
@@ -3075,14 +3206,12 @@ bool CWallet::UpgradeWallet(int version, bilingual_str& error)
void CWallet::postInitProcess()
{
- LOCK(cs_wallet);
-
// Add wallet transactions that aren't already in a block to mempool
// Do this here as mempool requires genesis block to be loaded
- ReacceptWalletTransactions();
+ ResubmitWalletTransactions(/*relay=*/false, /*force=*/true);
// Update wallet transactions with current mempool transactions.
- chain().requestMempoolTransactions(*this);
+ WITH_LOCK(cs_wallet, chain().requestMempoolTransactions(*this));
}
bool CWallet::BackupWallet(const std::string& strDest) const
@@ -3249,6 +3378,18 @@ std::unique_ptr<SigningProvider> CWallet::GetSolvingProvider(const CScript& scri
return nullptr;
}
+std::vector<WalletDescriptor> CWallet::GetWalletDescriptors(const CScript& script) const
+{
+ std::vector<WalletDescriptor> descs;
+ for (const auto spk_man: GetScriptPubKeyMans(script)) {
+ if (const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man)) {
+ LOCK(desc_spk_man->cs_desc_man);
+ descs.push_back(desc_spk_man->GetWalletDescriptor());
+ }
+ }
+ return descs;
+}
+
LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
{
if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
@@ -3310,6 +3451,29 @@ void CWallet::LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc)
}
}
+void CWallet::SetupDescriptorScriptPubKeyMans(const CExtKey& master_key)
+{
+ AssertLockHeld(cs_wallet);
+
+ for (bool internal : {false, true}) {
+ for (OutputType t : OUTPUT_TYPES) {
+ auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this));
+ if (IsCrypted()) {
+ if (IsLocked()) {
+ throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
+ }
+ if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, nullptr)) {
+ throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
+ }
+ }
+ spk_manager->SetupDescriptorGeneration(master_key, t, internal);
+ uint256 id = spk_manager->GetID();
+ m_spk_managers[id] = std::move(spk_manager);
+ AddActiveScriptPubKeyMan(id, t, internal);
+ }
+ }
+}
+
void CWallet::SetupDescriptorScriptPubKeyMans()
{
AssertLockHeld(cs_wallet);
@@ -3325,23 +3489,7 @@ void CWallet::SetupDescriptorScriptPubKeyMans()
CExtKey master_key;
master_key.SetSeed(seed_key);
- for (bool internal : {false, true}) {
- for (OutputType t : OUTPUT_TYPES) {
- auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this));
- if (IsCrypted()) {
- if (IsLocked()) {
- throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
- }
- if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, nullptr)) {
- throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
- }
- }
- spk_manager->SetupDescriptorGeneration(master_key, t, internal);
- uint256 id = spk_manager->GetID();
- m_spk_managers[id] = std::move(spk_manager);
- AddActiveScriptPubKeyMan(id, t, internal);
- }
- }
+ SetupDescriptorScriptPubKeyMans(master_key);
} else {
ExternalSigner signer = ExternalSignerScriptPubKeyMan::GetExternalSigner();
@@ -3354,7 +3502,7 @@ void CWallet::SetupDescriptorScriptPubKeyMans()
const UniValue& descriptor_vals = find_value(signer_res, internal ? "internal" : "receive");
if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
- std::string desc_str = desc_val.getValStr();
+ const std::string& desc_str = desc_val.getValStr();
FlatSigningProvider keys;
std::string desc_error;
std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, desc_error, false);
@@ -3390,7 +3538,7 @@ void CWallet::LoadActiveScriptPubKeyMan(uint256 id, OutputType type, bool intern
// Legacy wallets have only one ScriptPubKeyManager and it's active for all output and change types.
Assert(IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
- WalletLogPrintf("Setting spkMan to active: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
+ WalletLogPrintf("Setting spkMan to active: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
auto& spk_mans_other = internal ? m_external_spk_managers : m_internal_spk_managers;
auto spk_man = m_spk_managers.at(id).get();
@@ -3408,7 +3556,7 @@ void CWallet::DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool intern
{
auto spk_man = GetScriptPubKeyMan(type, internal);
if (spk_man != nullptr && spk_man->GetID() == id) {
- WalletLogPrintf("Deactivate spkMan: id = %s, type = %d, internal = %d\n", id.ToString(), static_cast<int>(type), static_cast<int>(internal));
+ WalletLogPrintf("Deactivate spkMan: id = %s, type = %s, internal = %s\n", id.ToString(), FormatOutputType(type), internal ? "true" : "false");
WalletBatch batch(GetDatabase());
if (!batch.EraseActiveScriptPubKeyMan(static_cast<uint8_t>(type), internal)) {
throw std::runtime_error(std::string(__func__) + ": erasing active ScriptPubKeyMan id failed");
@@ -3509,9 +3657,13 @@ ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const Flat
return nullptr;
}
- CTxDestination dest;
- if (!internal && ExtractDestination(script_pub_keys.at(0), dest)) {
- SetAddressBook(dest, label, "receive");
+ if (!internal) {
+ for (const auto& script : script_pub_keys) {
+ CTxDestination dest;
+ if (ExtractDestination(script, dest)) {
+ SetAddressBook(dest, label, "receive");
+ }
+ }
}
}
@@ -3520,4 +3672,472 @@ ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const Flat
return spk_man;
}
+
+bool CWallet::MigrateToSQLite(bilingual_str& error)
+{
+ AssertLockHeld(cs_wallet);
+
+ WalletLogPrintf("Migrating wallet storage database from BerkeleyDB to SQLite.\n");
+
+ if (m_database->Format() == "sqlite") {
+ error = _("Error: This wallet already uses SQLite");
+ return false;
+ }
+
+ // Get all of the records for DB type migration
+ std::unique_ptr<DatabaseBatch> batch = m_database->MakeBatch();
+ std::vector<std::pair<SerializeData, SerializeData>> records;
+ if (!batch->StartCursor()) {
+ error = _("Error: Unable to begin reading all records in the database");
+ return false;
+ }
+ bool complete = false;
+ while (true) {
+ CDataStream ss_key(SER_DISK, CLIENT_VERSION);
+ CDataStream ss_value(SER_DISK, CLIENT_VERSION);
+ bool ret = batch->ReadAtCursor(ss_key, ss_value, complete);
+ if (!ret) {
+ break;
+ }
+ SerializeData key(ss_key.begin(), ss_key.end());
+ SerializeData value(ss_value.begin(), ss_value.end());
+ records.emplace_back(key, value);
+ }
+ batch->CloseCursor();
+ batch.reset();
+ if (!complete) {
+ error = _("Error: Unable to read all records in the database");
+ return false;
+ }
+
+ // Close this database and delete the file
+ fs::path db_path = fs::PathFromString(m_database->Filename());
+ fs::path db_dir = db_path.parent_path();
+ m_database->Close();
+ fs::remove(db_path);
+
+ // Make new DB
+ DatabaseOptions opts;
+ opts.require_create = true;
+ opts.require_format = DatabaseFormat::SQLITE;
+ DatabaseStatus db_status;
+ std::unique_ptr<WalletDatabase> new_db = MakeDatabase(db_dir, opts, db_status, error);
+ assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists.
+ m_database.reset();
+ m_database = std::move(new_db);
+
+ // Write existing records into the new DB
+ batch = m_database->MakeBatch();
+ bool began = batch->TxnBegin();
+ assert(began); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
+ for (const auto& [key, value] : records) {
+ CDataStream ss_key(key, SER_DISK, CLIENT_VERSION);
+ CDataStream ss_value(value, SER_DISK, CLIENT_VERSION);
+ if (!batch->Write(ss_key, ss_value)) {
+ batch->TxnAbort();
+ m_database->Close();
+ fs::remove(m_database->Filename());
+ assert(false); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
+ }
+ }
+ bool committed = batch->TxnCommit();
+ assert(committed); // This is a critical error, the new db could not be written to. The original db exists as a backup, but we should not continue execution.
+ return true;
+}
+
+std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& error) const
+{
+ AssertLockHeld(cs_wallet);
+
+ LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
+ if (!legacy_spkm) {
+ error = _("Error: This wallet is already a descriptor wallet");
+ return std::nullopt;
+ }
+
+ std::optional<MigrationData> res = legacy_spkm->MigrateToDescriptor();
+ if (res == std::nullopt) {
+ error = _("Error: Unable to produce descriptors for this legacy wallet. Make sure the wallet is unlocked first");
+ return std::nullopt;
+ }
+ return res;
+}
+
+bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
+{
+ AssertLockHeld(cs_wallet);
+
+ LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
+ if (!legacy_spkm) {
+ error = _("Error: This wallet is already a descriptor wallet");
+ return false;
+ }
+
+ for (auto& desc_spkm : data.desc_spkms) {
+ if (m_spk_managers.count(desc_spkm->GetID()) > 0) {
+ error = _("Error: Duplicate descriptors created during migration. Your wallet may be corrupted.");
+ return false;
+ }
+ m_spk_managers[desc_spkm->GetID()] = std::move(desc_spkm);
+ }
+
+ // Remove the LegacyScriptPubKeyMan from disk
+ if (!legacy_spkm->DeleteRecords()) {
+ return false;
+ }
+
+ // Remove the LegacyScriptPubKeyMan from memory
+ m_spk_managers.erase(legacy_spkm->GetID());
+ m_external_spk_managers.clear();
+ m_internal_spk_managers.clear();
+
+ // Setup new descriptors
+ SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
+ if (!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
+ // Use the existing master key if we have it
+ if (data.master_key.key.IsValid()) {
+ SetupDescriptorScriptPubKeyMans(data.master_key);
+ } else {
+ // Setup with a new seed if we don't.
+ SetupDescriptorScriptPubKeyMans();
+ }
+ }
+
+ // Check if the transactions in the wallet are still ours. Either they belong here, or they belong in the watchonly wallet.
+ // We need to go through these in the tx insertion order so that lookups to spends works.
+ std::vector<uint256> txids_to_delete;
+ for (const auto& [_pos, wtx] : wtxOrdered) {
+ if (!IsMine(*wtx->tx) && !IsFromMe(*wtx->tx)) {
+ // Check it is the watchonly wallet's
+ // solvable_wallet doesn't need to be checked because transactions for those scripts weren't being watched for
+ if (data.watchonly_wallet) {
+ LOCK(data.watchonly_wallet->cs_wallet);
+ if (data.watchonly_wallet->IsMine(*wtx->tx) || data.watchonly_wallet->IsFromMe(*wtx->tx)) {
+ // Add to watchonly wallet
+ if (!data.watchonly_wallet->AddToWallet(wtx->tx, wtx->m_state)) {
+ error = _("Error: Could not add watchonly tx to watchonly wallet");
+ return false;
+ }
+ // Mark as to remove from this wallet
+ txids_to_delete.push_back(wtx->GetHash());
+ continue;
+ }
+ }
+ // Both not ours and not in the watchonly wallet
+ error = strprintf(_("Error: Transaction %s in wallet cannot be identified to belong to migrated wallets"), wtx->GetHash().GetHex());
+ return false;
+ }
+ }
+ // Do the removes
+ if (txids_to_delete.size() > 0) {
+ std::vector<uint256> deleted_txids;
+ if (ZapSelectTx(txids_to_delete, deleted_txids) != DBErrors::LOAD_OK) {
+ error = _("Error: Could not delete watchonly transactions");
+ return false;
+ }
+ if (deleted_txids != txids_to_delete) {
+ error = _("Error: Not all watchonly txs could be deleted");
+ return false;
+ }
+ // Tell the GUI of each tx
+ for (const uint256& txid : deleted_txids) {
+ NotifyTransactionChanged(txid, CT_UPDATED);
+ }
+ }
+
+ // Check the address book data in the same way we did for transactions
+ std::vector<CTxDestination> dests_to_delete;
+ for (const auto& addr_pair : m_address_book) {
+ // Labels applied to receiving addresses should go based on IsMine
+ if (addr_pair.second.purpose == "receive") {
+ if (!IsMine(addr_pair.first)) {
+ // Check the address book data is the watchonly wallet's
+ if (data.watchonly_wallet) {
+ LOCK(data.watchonly_wallet->cs_wallet);
+ if (data.watchonly_wallet->IsMine(addr_pair.first)) {
+ // Add to the watchonly. Preserve the labels, purpose, and change-ness
+ std::string label = addr_pair.second.GetLabel();
+ std::string purpose = addr_pair.second.purpose;
+ if (!purpose.empty()) {
+ data.watchonly_wallet->m_address_book[addr_pair.first].purpose = purpose;
+ }
+ if (!addr_pair.second.IsChange()) {
+ data.watchonly_wallet->m_address_book[addr_pair.first].SetLabel(label);
+ }
+ dests_to_delete.push_back(addr_pair.first);
+ continue;
+ }
+ }
+ if (data.solvable_wallet) {
+ LOCK(data.solvable_wallet->cs_wallet);
+ if (data.solvable_wallet->IsMine(addr_pair.first)) {
+ // Add to the solvable. Preserve the labels, purpose, and change-ness
+ std::string label = addr_pair.second.GetLabel();
+ std::string purpose = addr_pair.second.purpose;
+ if (!purpose.empty()) {
+ data.solvable_wallet->m_address_book[addr_pair.first].purpose = purpose;
+ }
+ if (!addr_pair.second.IsChange()) {
+ data.solvable_wallet->m_address_book[addr_pair.first].SetLabel(label);
+ }
+ dests_to_delete.push_back(addr_pair.first);
+ continue;
+ }
+ }
+ // Not ours, not in watchonly wallet, and not in solvable
+ error = _("Error: Address book data in wallet cannot be identified to belong to migrated wallets");
+ return false;
+ }
+ } else {
+ // Labels for everything else (send) should be cloned to all
+ if (data.watchonly_wallet) {
+ LOCK(data.watchonly_wallet->cs_wallet);
+ // Add to the watchonly. Preserve the labels, purpose, and change-ness
+ std::string label = addr_pair.second.GetLabel();
+ std::string purpose = addr_pair.second.purpose;
+ if (!purpose.empty()) {
+ data.watchonly_wallet->m_address_book[addr_pair.first].purpose = purpose;
+ }
+ if (!addr_pair.second.IsChange()) {
+ data.watchonly_wallet->m_address_book[addr_pair.first].SetLabel(label);
+ }
+ continue;
+ }
+ if (data.solvable_wallet) {
+ LOCK(data.solvable_wallet->cs_wallet);
+ // Add to the solvable. Preserve the labels, purpose, and change-ness
+ std::string label = addr_pair.second.GetLabel();
+ std::string purpose = addr_pair.second.purpose;
+ if (!purpose.empty()) {
+ data.solvable_wallet->m_address_book[addr_pair.first].purpose = purpose;
+ }
+ if (!addr_pair.second.IsChange()) {
+ data.solvable_wallet->m_address_book[addr_pair.first].SetLabel(label);
+ }
+ continue;
+ }
+ }
+ }
+ // Remove the things to delete
+ if (dests_to_delete.size() > 0) {
+ for (const auto& dest : dests_to_delete) {
+ if (!DelAddressBook(dest)) {
+ error = _("Error: Unable to remove watchonly address book data");
+ return false;
+ }
+ }
+ }
+
+ // Connect the SPKM signals
+ ConnectScriptPubKeyManNotifiers();
+ NotifyCanGetAddressesChanged();
+
+ WalletLogPrintf("Wallet migration complete.\n");
+
+ return true;
+}
+
+bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error, MigrationResult& res) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
+{
+ AssertLockHeld(wallet.cs_wallet);
+
+ // Get all of the descriptors from the legacy wallet
+ std::optional<MigrationData> data = wallet.GetDescriptorsForLegacy(error);
+ if (data == std::nullopt) return false;
+
+ // Create the watchonly and solvable wallets if necessary
+ if (data->watch_descs.size() > 0 || data->solvable_descs.size() > 0) {
+ DatabaseOptions options;
+ options.require_existing = false;
+ options.require_create = true;
+
+ // Make the wallets
+ options.create_flags = WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET | WALLET_FLAG_DESCRIPTORS;
+ if (wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
+ options.create_flags |= WALLET_FLAG_AVOID_REUSE;
+ }
+ if (wallet.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) {
+ options.create_flags |= WALLET_FLAG_KEY_ORIGIN_METADATA;
+ }
+ if (data->watch_descs.size() > 0) {
+ wallet.WalletLogPrintf("Making a new watchonly wallet containing the watched scripts\n");
+
+ DatabaseStatus status;
+ std::vector<bilingual_str> warnings;
+ std::string wallet_name = wallet.GetName() + "_watchonly";
+ data->watchonly_wallet = CreateWallet(context, wallet_name, std::nullopt, options, status, error, warnings);
+ if (status != DatabaseStatus::SUCCESS) {
+ error = _("Error: Failed to create new watchonly wallet");
+ return false;
+ }
+ res.watchonly_wallet = data->watchonly_wallet;
+ LOCK(data->watchonly_wallet->cs_wallet);
+
+ // Parse the descriptors and add them to the new wallet
+ for (const auto& [desc_str, creation_time] : data->watch_descs) {
+ // Parse the descriptor
+ FlatSigningProvider keys;
+ std::string parse_err;
+ std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, parse_err, /* require_checksum */ true);
+ assert(desc); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor
+ assert(!desc->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
+
+ // Add to the wallet
+ WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
+ data->watchonly_wallet->AddWalletDescriptor(w_desc, keys, "", false);
+ }
+
+ // Add the wallet to settings
+ UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
+ }
+ if (data->solvable_descs.size() > 0) {
+ wallet.WalletLogPrintf("Making a new watchonly wallet containing the unwatched solvable scripts\n");
+
+ DatabaseStatus status;
+ std::vector<bilingual_str> warnings;
+ std::string wallet_name = wallet.GetName() + "_solvables";
+ data->solvable_wallet = CreateWallet(context, wallet_name, std::nullopt, options, status, error, warnings);
+ if (status != DatabaseStatus::SUCCESS) {
+ error = _("Error: Failed to create new watchonly wallet");
+ return false;
+ }
+ res.solvables_wallet = data->solvable_wallet;
+ LOCK(data->solvable_wallet->cs_wallet);
+
+ // Parse the descriptors and add them to the new wallet
+ for (const auto& [desc_str, creation_time] : data->solvable_descs) {
+ // Parse the descriptor
+ FlatSigningProvider keys;
+ std::string parse_err;
+ std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, parse_err, /* require_checksum */ true);
+ assert(desc); // It shouldn't be possible to have the LegacyScriptPubKeyMan make an invalid descriptor
+ assert(!desc->IsRange()); // It shouldn't be possible to have LegacyScriptPubKeyMan make a ranged watchonly descriptor
+
+ // Add to the wallet
+ WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
+ data->solvable_wallet->AddWalletDescriptor(w_desc, keys, "", false);
+ }
+
+ // Add the wallet to settings
+ UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
+ }
+ }
+
+ // Add the descriptors to wallet, remove LegacyScriptPubKeyMan, and cleanup txs and address book data
+ if (!wallet.ApplyMigrationData(*data, error)) {
+ return false;
+ }
+ return true;
+}
+
+util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>&& wallet, WalletContext& context)
+{
+ MigrationResult res;
+ bilingual_str error;
+ std::vector<bilingual_str> warnings;
+
+ // Make a backup of the DB
+ std::string wallet_name = wallet->GetName();
+ fs::path this_wallet_dir = fs::absolute(fs::PathFromString(wallet->GetDatabase().Filename())).parent_path();
+ fs::path backup_filename = fs::PathFromString(strprintf("%s-%d.legacy.bak", wallet_name, GetTime()));
+ fs::path backup_path = this_wallet_dir / backup_filename;
+ if (!wallet->BackupWallet(fs::PathToString(backup_path))) {
+ return util::Error{_("Error: Unable to make a backup of your wallet")};
+ }
+ res.backup_path = backup_path;
+
+ // Unload the wallet so that nothing else tries to use it while we're changing it
+ if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
+ return util::Error{_("Unable to unload the wallet before migrating")};
+ }
+ UnloadWallet(std::move(wallet));
+
+ // Load the wallet but only in the context of this function.
+ // No signals should be connected nor should anything else be aware of this wallet
+ WalletContext empty_context;
+ empty_context.args = context.args;
+ DatabaseOptions options;
+ options.require_existing = true;
+ DatabaseStatus status;
+ std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(wallet_name, options, status, error);
+ if (!database) {
+ return util::Error{Untranslated("Wallet file verification failed.") + Untranslated(" ") + error};
+ }
+
+ std::shared_ptr<CWallet> local_wallet = CWallet::Create(empty_context, wallet_name, std::move(database), options.create_flags, error, warnings);
+ if (!local_wallet) {
+ return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
+ }
+
+ bool success = false;
+ {
+ LOCK(local_wallet->cs_wallet);
+
+ // First change to using SQLite
+ if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
+
+ // Do the migration, and cleanup if it fails
+ success = DoMigration(*local_wallet, context, error, res);
+ }
+
+ if (success) {
+ // Migration successful, unload the wallet locally, then reload it.
+ assert(local_wallet.use_count() == 1);
+ local_wallet.reset();
+ LoadWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
+ res.wallet_name = wallet_name;
+ } else {
+ // Migration failed, cleanup
+ // Copy the backup to the actual wallet dir
+ fs::path temp_backup_location = fsbridge::AbsPathJoin(GetWalletDir(), backup_filename);
+ fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);
+
+ // 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());
+
+ // Unload the wallet locally
+ assert(local_wallet.use_count() == 1);
+ local_wallet.reset();
+
+ // Make list of wallets to cleanup
+ std::vector<std::shared_ptr<CWallet>> created_wallets;
+ if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
+ if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));
+
+ // Get the directories to remove after unloading
+ for (std::shared_ptr<CWallet>& w : created_wallets) {
+ wallet_dirs.push_back(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
+ }
+
+ // Unload the wallets
+ for (std::shared_ptr<CWallet>& w : created_wallets) {
+ if (!RemoveWallet(context, w, /*load_on_start=*/false)) {
+ error += _("\nUnable to cleanup failed migration");
+ return util::Error{error};
+ }
+ UnloadWallet(std::move(w));
+ }
+
+ // Delete the wallet directories
+ for (fs::path& dir : wallet_dirs) {
+ fs::remove_all(dir);
+ }
+
+ // Restore the backup
+ DatabaseStatus status;
+ std::vector<bilingual_str> warnings;
+ if (!RestoreWallet(context, temp_backup_location, wallet_name, /*load_on_start=*/std::nullopt, status, error, warnings)) {
+ error += _("\nUnable to restore backup of wallet.");
+ return util::Error{error};
+ }
+
+ // Move the backup to the wallet dir
+ fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
+ fs::remove(temp_backup_location);
+
+ return util::Error{error};
+ }
+ return res;
+}
} // namespace wallet
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index bf42b3da9e..2f10c598b5 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -14,7 +14,9 @@
#include <policy/feerate.h>
#include <psbt.h>
#include <tinyformat.h>
+#include <util/hasher.h>
#include <util/message.h>
+#include <util/result.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/system.h>
@@ -36,6 +38,7 @@
#include <stdint.h>
#include <string>
#include <utility>
+#include <unordered_map>
#include <vector>
#include <boost/signals2/signal.hpp>
@@ -45,7 +48,6 @@ using LoadWalletFn = std::function<void(std::unique_ptr<interfaces::Wallet> wall
class CScript;
enum class FeeEstimateMode;
-struct FeeCalculation;
struct bilingual_str;
namespace wallet {
@@ -62,6 +64,7 @@ bool AddWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet);
bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings);
bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start);
std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context);
+std::shared_ptr<CWallet> GetDefaultWallet(WalletContext& context, size_t& count);
std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name);
std::shared_ptr<CWallet> LoadWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
@@ -90,7 +93,7 @@ static const CAmount DEFAULT_CONSOLIDATE_FEERATE{10000}; // 10 sat/vbyte
static const CAmount DEFAULT_MAX_AVOIDPARTIALSPEND_FEE = 0;
//! discourage APS fee higher than this amount
constexpr CAmount HIGH_APS_FEE{COIN / 10000};
-//! minimum recommended increment for BIP 125 replacement txs
+//! minimum recommended increment for replacement txs
static const CAmount WALLET_INCREMENTAL_RELAY_FEE = 5000;
//! Default for -spendzeroconfchange
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true;
@@ -99,7 +102,7 @@ static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS{true};
//! -txconfirmtarget default
static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6;
//! -walletrbf default
-static const bool DEFAULT_WALLET_RBF = false;
+static const bool DEFAULT_WALLET_RBF = true;
static const bool DEFAULT_WALLETBROADCAST = true;
static const bool DEFAULT_DISABLE_WALLET = false;
static const bool DEFAULT_WALLETCROSSCHAIN = false;
@@ -189,7 +192,7 @@ public:
}
//! Reserve an address
- bool GetReservedDestination(CTxDestination& pubkey, bool internal, bilingual_str& error);
+ util::Result<CTxDestination> GetReservedDestination(bool internal);
//! Return reserved address
void ReturnDestination();
//! Keep the address. Do not return it's key to the keypool when this object goes out of scope
@@ -247,7 +250,7 @@ private:
int nWalletVersion GUARDED_BY(cs_wallet){FEATURE_BASE};
/** The next scheduled rebroadcast of wallet transactions. */
- int64_t nNextResend = 0;
+ int64_t m_next_resend{GetDefaultNextResend()};
/** Whether this wallet will submit newly created transactions to the node's mempool and
* prompt rebroadcasts (see ResendWalletTransactions()). */
bool fBroadcastTransactions = false;
@@ -259,7 +262,7 @@ private:
* detect and report conflicts (double-spends or
* mutated transactions where the mutant gets mined).
*/
- typedef std::multimap<COutPoint, uint256> TxSpends;
+ typedef std::unordered_multimap<COutPoint, uint256, SaltedOutpointHasher> TxSpends;
TxSpends mapTxSpends GUARDED_BY(cs_wallet);
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void AddToSpends(const CWalletTx& wtx, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -313,7 +316,7 @@ private:
std::string m_name;
/** Internal database handle. */
- std::unique_ptr<WalletDatabase> const m_database;
+ std::unique_ptr<WalletDatabase> m_database;
/**
* The following is used to keep track of how far behind the wallet is
@@ -345,6 +348,8 @@ private:
*/
static bool AttachChain(const std::shared_ptr<CWallet>& wallet, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings);
+ static int64_t GetDefaultNextResend();
+
public:
/**
* Main wallet lock.
@@ -390,7 +395,7 @@ public:
/** Map from txid to CWalletTx for all transactions this wallet is
* interested in, including received and sent transactions. */
- std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
+ std::unordered_map<uint256, CWalletTx, SaltedTxidHasher> mapWallet GUARDED_BY(cs_wallet);
typedef std::multimap<int64_t, CWalletTx*> TxItems;
TxItems wtxOrdered;
@@ -505,11 +510,15 @@ public:
//! @return true if wtx is changed and needs to be saved to disk, otherwise false
using UpdateWalletTxFn = std::function<bool(CWalletTx& wtx, bool new_tx)>;
+ /**
+ * Add the transaction to the wallet, wrapping it up inside a CWalletTx
+ * @return the recently added wtx pointer or nullptr if there was a db write error.
+ */
CWalletTx* AddToWallet(CTransactionRef tx, const TxState& state, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true, bool rescanning_old_block = false);
bool LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void transactionAddedToMempool(const CTransactionRef& tx, uint64_t mempool_sequence) override;
- void blockConnected(const CBlock& block, int height) override;
- void blockDisconnected(const CBlock& block, int height) override;
+ void blockConnected(const interfaces::BlockInfo& block) override;
+ void blockDisconnected(const interfaces::BlockInfo& block) override;
void updatedBlockTip() override;
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
@@ -528,10 +537,13 @@ public:
//! USER_ABORT.
uint256 last_failed_block;
};
- ScanResult ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate);
+ ScanResult ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate, const bool save_progress);
void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override;
- void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- void ResendWalletTransactions();
+ /** Set the next time this wallet should resend transactions to 12-36 hours from now, ~1 day on average. */
+ void SetNextResend() { m_next_resend = GetDefaultNextResend(); }
+ /** Return true if all conditions for periodically resending transactions are met. */
+ bool ShouldResend() const;
+ void ResubmitWalletTransactions(bool relay, bool force);
OutputType TransactionChangeType(const std::optional<OutputType>& change_type, const std::vector<CRecipient>& vecSend) const;
@@ -635,7 +647,30 @@ public:
std::optional<int64_t> GetOldestKeyPoolTime() const;
- std::set<CTxDestination> GetLabelAddresses(const std::string& label) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ // Filter struct for 'ListAddrBookAddresses'
+ struct AddrBookFilter {
+ // Fetch addresses with the provided label
+ std::optional<std::string> m_op_label{std::nullopt};
+ // Don't include change addresses by default
+ bool ignore_change{true};
+ };
+
+ /**
+ * Filter and retrieve destinations stored in the addressbook
+ */
+ std::vector<CTxDestination> ListAddrBookAddresses(const std::optional<AddrBookFilter>& filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ /**
+ * Retrieve all the known labels in the address book
+ */
+ std::set<std::string> ListAddrBookLabels(const std::string& purpose) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ /**
+ * Walk-through the address book entries.
+ * Stops when the provided 'ListAddrBookFunc' returns false.
+ */
+ using ListAddrBookFunc = std::function<void(const CTxDestination& dest, const std::string& label, const std::string& purpose, bool is_change)>;
+ void ForEachAddrBookEntry(const ListAddrBookFunc& func) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Marks all outputs in each one of the destinations dirty, so their cache is
@@ -643,8 +678,8 @@ public:
*/
void MarkDestinationsDirty(const std::set<CTxDestination>& destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, bilingual_str& error);
- bool GetNewChangeDestination(const OutputType type, CTxDestination& dest, bilingual_str& error);
+ util::Result<CTxDestination> GetNewDestination(const OutputType type, const std::string label);
+ util::Result<CTxDestination> GetNewChangeDestination(const OutputType type);
isminetype IsMine(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
isminetype IsMine(const CScript& script) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -655,6 +690,7 @@ public:
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
isminetype IsMine(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ isminetype IsMine(const COutPoint& outpoint) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** should probably be renamed to IsRelevantToMe */
bool IsFromMe(const CTransaction& tx) const;
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;
@@ -685,7 +721,7 @@ public:
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
- bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+ bool HasWalletSpend(const CTransactionRef& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Flush wallet (bitdb flush)
void Flush();
@@ -737,7 +773,7 @@ public:
/* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */
bool AbandonTransaction(const uint256& hashTx);
- /** Mark a transaction as replaced by another transaction (e.g., BIP 125). */
+ /** Mark a transaction as replaced by another transaction. */
bool MarkReplaced(const uint256& originalHash, const uint256& newHash);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
@@ -775,8 +811,9 @@ public:
bool IsWalletFlagSet(uint64_t flag) const override;
/** overwrite all flags by the given uint64_t
- returns false if unknown, non-tolerable flags are present */
- bool AddWalletFlags(uint64_t flags);
+ flags must be uninitialised (or 0)
+ only known flags may be present */
+ void InitWalletFlags(uint64_t flags);
/** Loads the flags into the wallet. (used by LoadWallet) */
bool LoadWalletFlags(uint64_t flags);
@@ -816,6 +853,9 @@ public:
std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script) const;
std::unique_ptr<SigningProvider> GetSolvingProvider(const CScript& script, SignatureData& sigdata) const;
+ //! Get the wallet descriptors for a script.
+ std::vector<WalletDescriptor> GetWalletDescriptors(const CScript& script) const;
+
//! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan();
@@ -872,6 +912,7 @@ public:
void DeactivateScriptPubKeyMan(uint256 id, OutputType type, bool internal);
//! Create new DescriptorScriptPubKeyMans and add them to the wallet
+ void SetupDescriptorScriptPubKeyMans(const CExtKey& master_key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void SetupDescriptorScriptPubKeyMans() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Return the DescriptorScriptPubKeyMan for a WalletDescriptor if it is already in the wallet
@@ -884,6 +925,20 @@ public:
//! Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type
ScriptPubKeyMan* AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ /** Move all records from the BDB database to a new SQLite database for storage.
+ * The original BDB file will be deleted and replaced with a new SQLite file.
+ * A backup is not created.
+ * May crash if something unexpected happens in the filesystem.
+ */
+ bool MigrateToSQLite(bilingual_str& error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ //! Get all of the descriptors from a legacy wallet
+ std::optional<MigrationData> GetDescriptorsForLegacy(bilingual_str& error) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+ //! Adds the ScriptPubKeyMans given in MigrationData to this wallet, removes LegacyScriptPubKeyMan,
+ //! and where needed, moves tx and address book entries to watchonly_wallet or solvable_wallet
+ bool ApplyMigrationData(MigrationData& data, bilingual_str& error) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
};
/**
@@ -896,8 +951,11 @@ void MaybeResendWalletTxs(WalletContext& context);
class WalletRescanReserver
{
private:
+ using Clock = std::chrono::steady_clock;
+ using NowFn = std::function<Clock::time_point()>;
CWallet& m_wallet;
bool m_could_reserve;
+ NowFn m_now;
public:
explicit WalletRescanReserver(CWallet& w) : m_wallet(w), m_could_reserve(false) {}
@@ -918,6 +976,10 @@ public:
return (m_could_reserve && m_wallet.fScanningWallet);
}
+ Clock::time_point now() const { return m_now ? m_now() : Clock::now(); };
+
+ void setNow(NowFn now) { m_now = std::move(now); }
+
~WalletRescanReserver()
{
if (m_could_reserve) {
@@ -932,9 +994,19 @@ bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name);
//! Remove wallet name from persistent configuration so it will not be loaded on startup.
bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name);
-bool DummySignInput(const SigningProvider& provider, CTxIn &tx_in, const CTxOut &txout, bool use_max_sig);
+bool DummySignInput(const SigningProvider& provider, CTxIn &tx_in, const CTxOut &txout, const CCoinControl* coin_control = nullptr);
bool FillInputToWeight(CTxIn& txin, int64_t target_weight);
+
+struct MigrationResult {
+ std::string wallet_name;
+ std::shared_ptr<CWallet> watchonly_wallet;
+ std::shared_ptr<CWallet> solvables_wallet;
+ fs::path backup_path;
+};
+
+//! Do all steps to migrate a legacy wallet to a descriptor wallet
+util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>&& wallet, WalletContext& context);
} // namespace wallet
#endif // BITCOIN_WALLET_WALLET_H
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 79e0a330b7..6a8f0d2481 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -59,6 +59,7 @@ const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"};
const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"};
const std::string WATCHMETA{"watchmeta"};
const std::string WATCHS{"watchs"};
+const std::unordered_set<std::string> LEGACY_TYPES{CRYPTED_KEY, CSCRIPT, DEFAULTKEY, HDCHAIN, KEYMETA, KEY, OLD_KEY, POOL, WATCHMETA, WATCHS};
} // namespace DBKeys
//
@@ -313,6 +314,7 @@ public:
std::map<std::pair<uint256, CKeyID>, std::pair<CPubKey, std::vector<unsigned char>>> m_descriptor_crypt_keys;
std::map<uint160, CHDChain> m_hd_chains;
bool tx_corrupt{false};
+ bool descriptor_unknown{false};
CWalletScanState() = default;
};
@@ -626,7 +628,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
uint256 id;
ssKey >> id;
WalletDescriptor desc;
- ssValue >> desc;
+ try {
+ ssValue >> desc;
+ } catch (const std::ios_base::failure& e) {
+ strErr = e.what();
+ wss.descriptor_unknown = true;
+ return false;
+ }
if (wss.m_descriptor_caches.count(id) == 0) {
wss.m_descriptor_caches[id] = DescriptorCache();
}
@@ -766,6 +774,12 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
DBErrors result = DBErrors::LOAD_OK;
LOCK(pwallet->cs_wallet);
+
+ // Last client version to open this wallet
+ int last_client = CLIENT_VERSION;
+ bool has_last_client = m_batch->Read(DBKeys::VERSION, last_client);
+ pwallet->WalletLogPrintf("Wallet file version = %d, last client version = %d\n", pwallet->GetVersion(), last_client);
+
try {
int nMinVersion = 0;
if (m_batch->Read(DBKeys::MINVERSION, nMinVersion)) {
@@ -831,6 +845,13 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
// Set tx_corrupt back to false so that the error is only printed once (per corrupt tx)
wss.tx_corrupt = false;
result = DBErrors::CORRUPT;
+ } else if (wss.descriptor_unknown) {
+ strErr = strprintf("Error: Unrecognized descriptor found in wallet %s. ", pwallet->GetName());
+ strErr += (last_client > CLIENT_VERSION) ? "The wallet might had been created on a newer version. " :
+ "The database might be corrupted or the software version is not compatible with one of your wallet descriptors. ";
+ strErr += "Please try running the latest software version";
+ pwallet->WalletLogPrintf("%s\n", strErr);
+ return DBErrors::UNKNOWN_DESCRIPTOR;
} else {
// Leave other errors alone, if we try to fix them we might make things worse.
fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
@@ -856,18 +877,18 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
}
// Set the descriptor caches
- for (auto desc_cache_pair : wss.m_descriptor_caches) {
+ for (const auto& desc_cache_pair : wss.m_descriptor_caches) {
auto spk_man = pwallet->GetScriptPubKeyMan(desc_cache_pair.first);
assert(spk_man);
((DescriptorScriptPubKeyMan*)spk_man)->SetCache(desc_cache_pair.second);
}
// Set the descriptor keys
- for (auto desc_key_pair : wss.m_descriptor_keys) {
+ for (const auto& desc_key_pair : wss.m_descriptor_keys) {
auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
((DescriptorScriptPubKeyMan*)spk_man)->AddKey(desc_key_pair.first.second, desc_key_pair.second);
}
- for (auto desc_key_pair : wss.m_descriptor_crypt_keys) {
+ for (const auto& desc_key_pair : wss.m_descriptor_crypt_keys) {
auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
((DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey(desc_key_pair.first.second, desc_key_pair.second.first, desc_key_pair.second.second);
}
@@ -883,13 +904,6 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
if (result != DBErrors::LOAD_OK)
return result;
- // Last client version to open this wallet, was previously the file version number
- int last_client = CLIENT_VERSION;
- m_batch->Read(DBKeys::VERSION, last_client);
-
- int wallet_version = pwallet->GetVersion();
- pwallet->WalletLogPrintf("Wallet File Version = %d\n", wallet_version > 0 ? wallet_version : last_client);
-
pwallet->WalletLogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total. Unknown wallet records: %u\n",
wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys, wss.m_unknown_records);
@@ -909,7 +923,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
if (wss.fIsEncrypted && (last_client == 40000 || last_client == 50000))
return DBErrors::NEED_REWRITE;
- if (last_client < CLIENT_VERSION) // Update
+ if (!has_last_client || last_client != CLIENT_VERSION) // Update
m_batch->Write(DBKeys::VERSION, CLIENT_VERSION);
if (wss.fAnyUnordered)
@@ -1085,6 +1099,45 @@ bool WalletBatch::WriteWalletFlags(const uint64_t flags)
return WriteIC(DBKeys::FLAGS, flags);
}
+bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)
+{
+ // Get cursor
+ if (!m_batch->StartCursor())
+ {
+ return false;
+ }
+
+ // Iterate the DB and look for any records that have the type prefixes
+ while (true)
+ {
+ // Read next record
+ CDataStream key(SER_DISK, CLIENT_VERSION);
+ CDataStream value(SER_DISK, CLIENT_VERSION);
+ bool complete;
+ bool ret = m_batch->ReadAtCursor(key, value, complete);
+ if (complete) {
+ break;
+ }
+ else if (!ret)
+ {
+ m_batch->CloseCursor();
+ return false;
+ }
+
+ // Make a copy of key to avoid data being deleted by the following read of the type
+ Span<const unsigned char> key_data = MakeUCharSpan(key);
+
+ std::string type;
+ key >> type;
+
+ if (types.count(type) > 0) {
+ m_batch->Erase(key_data);
+ }
+ }
+ m_batch->CloseCursor();
+ return true;
+}
+
bool WalletBatch::TxnBegin()
{
return m_batch->TxnBegin();
@@ -1186,13 +1239,36 @@ std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase()
}
/** Return object for accessing temporary in-memory database. */
-std::unique_ptr<WalletDatabase> CreateMockWalletDatabase()
+std::unique_ptr<WalletDatabase> CreateMockWalletDatabase(DatabaseOptions& options)
{
- DatabaseOptions options;
+
+ std::optional<DatabaseFormat> format;
+ if (options.require_format) format = options.require_format;
+ if (!format) {
+#ifdef USE_BDB
+ format = DatabaseFormat::BERKELEY;
+#endif
+#ifdef USE_SQLITE
+ format = DatabaseFormat::SQLITE;
+#endif
+ }
+
+ if (format == DatabaseFormat::SQLITE) {
#ifdef USE_SQLITE
- return std::make_unique<SQLiteDatabase>("", "", options, true);
-#elif USE_BDB
+ return std::make_unique<SQLiteDatabase>(":memory:", "", options, true);
+#endif
+ assert(false);
+ }
+
+#ifdef USE_BDB
return std::make_unique<BerkeleyDatabase>(std::make_shared<BerkeleyEnvironment>(), "", options);
#endif
+ assert(false);
+}
+
+std::unique_ptr<WalletDatabase> CreateMockWalletDatabase()
+{
+ DatabaseOptions options;
+ return CreateMockWalletDatabase(options);
}
} // namespace wallet
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 3dfe781d56..da6efe534b 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -51,7 +51,8 @@ enum class DBErrors
EXTERNAL_SIGNER_SUPPORT_REQUIRED,
LOAD_FAIL,
NEED_REWRITE,
- NEED_RESCAN
+ NEED_RESCAN,
+ UNKNOWN_DESCRIPTOR
};
namespace DBKeys {
@@ -84,6 +85,9 @@ extern const std::string WALLETDESCRIPTORCKEY;
extern const std::string WALLETDESCRIPTORKEY;
extern const std::string WATCHMETA;
extern const std::string WATCHS;
+
+// Keys in this set pertain only to the legacy wallet (LegacyScriptPubKeyMan) and are removed during migration from legacy to descriptors.
+extern const std::unordered_set<std::string> LEGACY_TYPES;
} // namespace DBKeys
/* simple HD chain data model */
@@ -276,6 +280,9 @@ public:
//! write the hdchain model (external chain child index counter)
bool WriteHDChain(const CHDChain& chain);
+ //! Delete records of the given types
+ bool EraseRecords(const std::unordered_set<std::string>& types);
+
bool WriteWalletFlags(const uint64_t flags);
//! Begin a new transaction
bool TxnBegin();
@@ -301,6 +308,7 @@ bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, st
std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase();
/** Return object for accessing temporary in-memory database. */
+std::unique_ptr<WalletDatabase> CreateMockWalletDatabase(DatabaseOptions& options);
std::unique_ptr<WalletDatabase> CreateMockWalletDatabase();
} // namespace wallet
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
index 769175b5a8..e991bc0814 100644
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -34,7 +34,7 @@ static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flag
LOCK(wallet_instance->cs_wallet);
wallet_instance->SetMinVersion(FEATURE_LATEST);
- wallet_instance->AddWalletFlags(wallet_creation_flags);
+ wallet_instance->InitWalletFlags(wallet_creation_flags);
if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index 788d41ceb7..8434d64fb5 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -104,6 +104,20 @@ public:
WalletDescriptor() {}
WalletDescriptor(std::shared_ptr<Descriptor> descriptor, uint64_t creation_time, int32_t range_start, int32_t range_end, int32_t next_index) : descriptor(descriptor), creation_time(creation_time), range_start(range_start), range_end(range_end), next_index(next_index) {}
};
+
+class CWallet;
+class DescriptorScriptPubKeyMan;
+
+/** struct containing information needed for migrating legacy wallets to descriptor wallets */
+struct MigrationData
+{
+ CExtKey master_key;
+ std::vector<std::pair<std::string, int64_t>> watch_descs;
+ std::vector<std::pair<std::string, int64_t>> solvable_descs;
+ std::vector<std::unique_ptr<DescriptorScriptPubKeyMan>> desc_spkms;
+ std::shared_ptr<CWallet> watchonly_wallet{nullptr};
+ std::shared_ptr<CWallet> solvable_wallet{nullptr};
+};
} // namespace wallet
#endif // BITCOIN_WALLET_WALLETUTIL_H
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 26618735f6..b9b7019a3c 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -8,7 +8,7 @@
#include <zmq.h>
-#include <validation.h>
+#include <primitives/block.h>
#include <util/system.h>
CZMQNotificationInterface::CZMQNotificationInterface() : pcontext(nullptr)
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index 011336bf72..51c8ad515e 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -11,7 +11,6 @@
#include <rpc/server.h>
#include <streams.h>
#include <util/system.h>
-#include <validation.h> // For cs_main
#include <zmq/zmqutil.h>
#include <zmq.h>
diff --git a/test/README.md b/test/README.md
index 6ca7cc0016..7d4a26fb4e 100644
--- a/test/README.md
+++ b/test/README.md
@@ -95,12 +95,14 @@ Run all possible tests with
test/functional/test_runner.py --extended
```
-In order to run backwards compatibility tests, download the previous node binaries:
+In order to run backwards compatibility tests, first run:
```
-test/get_previous_releases.py -b v23.0 v22.0 v0.21.0 v0.20.1 v0.19.1 v0.18.1 v0.17.2 v0.16.3 v0.15.2 v0.14.3
+test/get_previous_releases.py -b
```
+to download the necessary previous release binaries.
+
By default, up to 4 tests will be run in parallel by test_runner. To specify
how many jobs to run, append `--jobs=n`
diff --git a/test/functional/README.md b/test/functional/README.md
index 914dbfd977..1bd618a0c3 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -28,7 +28,9 @@ don't have test cases for.
could lead to bugs and issues in the test code.
- Use [type hints](https://docs.python.org/3/library/typing.html) in your code to improve code readability
and to detect possible bugs earlier.
-- Avoid wildcard imports
+- Avoid wildcard imports.
+- If more than one name from a module is needed, use lexicographically sorted multi-line imports
+ in order to reduce the possibility of potential merge conflicts.
- Use a module-level docstring to describe what the test is testing, and how it
is testing it.
- When subclassing the BitcoinTestFramework, place overrides for the
diff --git a/test/functional/data/rpc_decodescript.json b/test/functional/data/rpc_decodescript.json
index 8903f5efac..4a15ae8792 100644
--- a/test/functional/data/rpc_decodescript.json
+++ b/test/functional/data/rpc_decodescript.json
@@ -4,7 +4,7 @@
{
"asm": "1 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"address": "bcrt1pamhwamhwamhwamhwamhwamhwamhwamhwamhwamhwamhwamhwamhqz6nvlh",
- "desc": "addr(bcrt1pamhwamhwamhwamhwamhwamhwamhwamhwamhwamhwamhwamhwamhqz6nvlh)#v52jnujz",
+ "desc": "rawtr(eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee)#jk7c6kys",
"type": "witness_v1_taproot"
}
],
diff --git a/test/functional/data/rpc_psbt.json b/test/functional/data/rpc_psbt.json
index 8672400a92..3127350872 100644
--- a/test/functional/data/rpc_psbt.json
+++ b/test/functional/data/rpc_psbt.json
@@ -27,7 +27,28 @@
"cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQQAAQQBagA=",
"cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQUAAQUBUQA=",
"cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQcAAQcBUQA=",
- "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQgBAAEIAwEBUQA="
+ "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQgBAAEIAwEBUQA=",
+ "cHNidP8BAHECAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Anh8AQAAAAAAFgAUg6fjS9mf8DpJYu+KGhAbspVGHs5gawQqAQAAABYAFHrDad8bIOAz1hFmI5V7CsSfPFLoAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXARchAv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyAAAA",
+ "cHNidP8BAHECAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Anh8AQAAAAAAFgAUg6fjS9mf8DpJYu+KGhAbspVGHs5gawQqAQAAABYAFHrDad8bIOAz1hFmI5V7CsSfPFLoAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXARM/Fzuz02wHSvtxb+xjB6BpouRQuZXzyCeFlFq43w4kJg3NcDsMvzTeOZGEqUgawrNYbbZgHwJqd/fkk4SBvDR1AAAA",
+ "cHNidP8BAHECAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Anh8AQAAAAAAFgAUg6fjS9mf8DpJYu+KGhAbspVGHs5gawQqAQAAABYAFHrDad8bIOAz1hFmI5V7CsSfPFLoAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXARNCFzuz02wHSvtxb+xjB6BpouRQuZXzyCeFlFq43w4kJg3NcDsMvzTeOZGEqUgawrNYbbZgHwJqd/fkk4SBvDR1FwGqAAAA",
+ "cHNidP8BAHECAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Anh8AQAAAAAAFgAUg6fjS9mf8DpJYu+KGhAbspVGHs5gawQqAQAAABYAFHrDad8bIOAz1hFmI5V7CsSfPFLoAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXIhYC/jSQZMmNbiqFP6PJsSvYswShnBlcYO+n7iOTBG0/ojIZAHcrLadWAACAAQAAgAAAAIABAAAAAAAAAAAAAA==",
+ "cHNidP8BAH0CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Aoh7AQAAAAAAFgAUI4KHHH6EIaAAk/dU2RKB5nWHS59gawQqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXAAABBSEC/jSQZMmNbiqFP6PJsSvYswShnBlcYO+n7iOTBG0/ojIA",
+ "cHNidP8BAH0CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Aoh7AQAAAAAAFgAUI4KHHH6EIaAAk/dU2RKB5nWHS59gawQqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXAAAiBwL+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMhkAdystp1YAAIABAACAAAAAgAEAAAAAAAAAAA==",
+ "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJCFAIssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20s2XDhX1P8DIL5UP1WD/qRm3YXK+AXNoqJkTrwdPQAsJQIl1aqNznMxonsD886NgvjLMC1mxbpOh6LtGBXJrLKej/3BsQXZkljKyzGjh+RK4pXjjcZzncQiFx6lm9JvNQ8sAAA==",
+ "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJBFCyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwlCiXVqo3OczGiewPzzo2C+MswLWbFuk6Hou0YFcmssp6P/cGxBdmSWMrLMaOH5ErileONxnOdxCIXHqWb0m81DywEBAAA=",
+ "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJBFCyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwk5iXVqo3OczGiewPzzo2C+MswLWbFuk6Hou0YFcmssp6P/cGxBdmSWMrLMaOH5ErileONxnOdxCIXHqWb0m81DywAA",
+ "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJjFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4fgAIyAssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20qzAAAA=",
+ "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJhFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4SMgLLE6xoJI3oBqpqNlnPPAPraCHQnIEUpOho/r3oZbttKswAAA"
+ ],
+ "invalid_with_msg": [
+ [
+ "cHNidP8BAKOro2MDAwMDA5ggCAAA////CQAtAAD+///1AAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAD+///1Zm9ybmV3nWx1Y2vmelLmegAAAAAAAAAAAAAAAAAAAAMKAwMDAwMDAwMDAwMACvMBA3FkAAAAAAAAAAAABAAlAAAAAAAAACEWDQ0zDQ0NDQ0NDQ0NCwEAAH9/f39/fwMAAABNo6P///kAAA==",
+ "Input Taproot BIP32 keypath has an invalid length"
+ ],
+ [
+ "cHNidP8BAIkCAAAAAapfm08b0MipBvW9thL06f8rMbeazW7TIa0W9plHj4WoAAAAAAD9////AoCWmAAAAAAAIlEgC+blBlIP1iijRWxqjw1u9H02sqr7y8fno6/LdnvGqPl895x2AAAAACJRIM5wyjSexMbADl4K+AI1/68zyaDlE7guKvrEDUAjwqU1AAAAAAABASsAlDV3AAAAACJRIDfCpO/CIAqc0JKgBhsCfaPGdyroYtmH+4gQK/Mnn72UIRZGOixxmh9h2gqDIecYHcQHRa8w+Sokc//iDiqXz7uMGRkAHzYIzlYAAIABAACAAAAAgAAAAABhAAAAARcgRjoscZofYdoKgyHnGB3EB0WvMPkqJHP/4g4ql8+7jBkAAQUg1YCB33LpmkGemw3ncz7fcnjhL/bBG/PjH8vpgr2L3cUBBgAhB9WAgd9y6ZpBnpsN53M+33J44S/2wRvz4x/L6YK9i93FGQAfNgjOVgAAgAEAAIAAAACAAAAAAGIAAAAAAQUg9jMNus8cd+GAosBk9wn+pNP9wn7A+jy2Vq0cy+siJ8wBBgAhB/YzDbrPHHfhgKLAZPcJ/qTT/cJ+wPo8tlatHMvrIifMGQAfNgjOVgAAgAEAAIAAAACAAQAAAFEBAAAA",
+ "Output Taproot tree must not be empty"
+ ]
],
"valid" : [
"cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA",
@@ -43,7 +64,13 @@
"cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAFQoYn3yLGjhv/o7tkbODDHp7zR53jAIBAhUK8pG6UBXfNIyAhT+luw95RvXJ4bMBAQAAAA==",
"cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAIQtL9RIvNEVUxTveLruM0rfj0WAK1jHDhaXXzOI8d4VFmgEBIQuhKHH+4hD7hhkpHq6hlFgcvSUx5LI3WdIl9oBpI/YyIgIBAgAAAA==",
"cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAFQwVzEnhkcvFINkZRGAKXLd69qoykQIBAhUMxRtmvO1eRJEAG9cCZpdw3M9ECYIBAQAAAA==",
- "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAIQ12pWrO2RXSUT3NhMLDeLLoqlzWMrW3HKLyrFsOOmSb2wIBAiENnBLP3ATHRYTXh6w9I3chMsGFJLx6so3sQhm4/FtCX3ABAQAAAA=="
+ "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAIQ12pWrO2RXSUT3NhMLDeLLoqlzWMrW3HKLyrFsOOmSb2wIBAiENnBLP3ATHRYTXh6w9I3chMsGFJLx6so3sQhm4/FtCX3ABAQAAAA==",
+ "cHNidP8BAFICAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAFgAUdo4e60z0IIZgM/gKzv8PlyB0SWkAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1chFv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyGQB3Ky2nVgAAgAEAAIAAAACAAQAAAAAAAAABFyD+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMgAiAgNrdyptt02HU8mKgnlY3mx4qzMSEJ830+AwRIQkLs5z2Bh3Ky2nVAAAgAEAAIAAAACAAAAAAAAAAAAA",
+ "cHNidP8BAFICAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAFgAUdo4e60z0IIZgM/gKzv8PlyB0SWkAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1cBE0C7U+yRe62dkGrxuocYHEi4as5aritTYFpyXKdGJWMUdvxvW67a9PLuD0d/NvWPOXDVuCc7fkl7l68uPxJcl680IRb+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMhkAdystp1YAAIABAACAAAAAgAEAAAAAAAAAARcg/jSQZMmNbiqFP6PJsSvYswShnBlcYO+n7iOTBG0/ojIAIgIDa3cqbbdNh1PJioJ5WN5seKszEhCfN9PgMESEJC7Oc9gYdystp1QAAIABAACAAAAAgAAAAAAAAAAAAA==",
+ "cHNidP8BAF4CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAIlEgg2mORYxmZOFZXXXaJZfeHiLul9eY5wbEwKS1qYI810MAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1chFv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyGQB3Ky2nVgAAgAEAAIAAAACAAQAAAAAAAAABFyD+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMgABBSARJNp67JLM0GyVRWJkf0N7E4uVchqEvivyJ2u92rPmcSEHESTaeuySzNBslUViZH9DexOLlXIahL4r8idrvdqz5nEZAHcrLadWAACAAQAAgAAAAIAAAAAABQAAAAA=",
+ "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgg2mORYxmZOFZXXXaJZfeHiLul9eY5wbEwKS1qYI810MAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJiFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4fgjICyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSrMBCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wJfG5v6l/3FP9XJEmZkIEOQG6YqhD1v35fZ4S8HQqabOIyBDILC/FvARtT6nvmFZJKp/J+XSmtIOoRVdhIZ2w7rRsqzAYhXBUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsDNlw4V9T/AyC+VD9Vg/6kZt2FyvgFzaKiZE68HT0ALCRFfLkkK98xFxPeFEfNgV85cWlxWMlop+0TfwgPzVuH4IyD6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqazAIRYssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20jkBzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwl3Ky2nVgAAgAEAAIACAACAAAAAAAAAAAAhFkMgsL8W8BG1Pqe+YVkkqn8n5dKa0g6hFV2EhnbDutGyOQERXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+HcrLadWAACAAQAAgAEAAIAAAAAAAAAAACEWUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAFAHxGHl0hFvoPejzvOx0MCmzn0m4XraCy5cktGe+tSLQYWcuKRRypOQFvfWIFnpSXoaSiZ1admHbaYBAa/zjjUpubk5zn+RrpcHcrLadWAACAAQAAgAMAAIAAAAAAAAAAAAEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARgg8DYuL3Wm9CClvePrIh2WrmcgzyX4GJDJWx13WstRXmUAAQUgESTaeuySzNBslUViZH9DexOLlXIahL4r8idrvdqz5nEhBxEk2nrskszQbJVFYmR/Q3sTi5VyGoS+K/Ina73as+ZxGQB3Ky2nVgAAgAEAAIAAAACAAAAAAAUAAAAA",
+ "cHNidP8BAF4CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAIlEgCoy9yG3hzhwPnK6yLW33ztNoP+Qj4F0eQCqHk0HW9vUAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1chFv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyGQB3Ky2nVgAAgAEAAIAAAACAAQAAAAAAAAABFyD+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMgABBSBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wAEGbwLAIiBzblcpAP4SUliaIUPI88efcaBBLSNTr3VelwHHgmlKAqwCwCIgYxxfO1gyuPvev7GXBM7rMjwh9A96JPQ9aO8MwmsSWWmsAcAiIET6pJoDON5IjI3//s37bzKfOAvVZu8gyN9tgT6rHEJzrCEHRPqkmgM43kiMjf/+zftvMp84C9Vm7yDI322BPqscQnM5AfBreYuSoQ7ZqdC7/Trxc6U7FhfaOkFZygCCFs2Fay4Odystp1YAAIABAACAAQAAgAAAAAADAAAAIQdQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wAUAfEYeXSEHYxxfO1gyuPvev7GXBM7rMjwh9A96JPQ9aO8MwmsSWWk5ARis5AmIl4Xg6nDO67jhyokqenjq7eDy4pbPQ1lhqPTKdystp1YAAIABAACAAgAAgAAAAAADAAAAIQdzblcpAP4SUliaIUPI88efcaBBLSNTr3VelwHHgmlKAjkBKaW0kVCQFi11mv0/4Pk/ozJgVtC0CIy5M8rngmy42Cx3Ky2nVgAAgAEAAIADAACAAAAAAAMAAAAA",
+ "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgg2mORYxmZOFZXXXaJZfeHiLul9eY5wbEwKS1qYI810MAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJBFCyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwlAv4GNl1fW/+tTi6BX+0wfxOD17xhudlvrVkeR4Cr1/T1eJVHU404z2G8na4LJnHmu0/A5Wgge/NLMLGXdfmk9eUEUQyCwvxbwEbU+p75hWSSqfyfl0prSDqEVXYSGdsO60bIRXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+EDh8atvq/omsjbyGDNxncHUKKt2jYD5H5mI2KvvR7+4Y7sfKlKfdowV8AzjTsKDzcB+iPhCi+KPbvZAQ8MpEYEaQRT6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqW99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwQOwfA3kgZGHIM0IoVCMyZwirAx8NpKJT7kWq+luMkgNNi2BUkPjNE+APmJmJuX4hX6o28S3uNpPS2szzeBwXV/ZiFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4fgjICyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSrMBCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wJfG5v6l/3FP9XJEmZkIEOQG6YqhD1v35fZ4S8HQqabOIyBDILC/FvARtT6nvmFZJKp/J+XSmtIOoRVdhIZ2w7rRsqzAYhXBUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsDNlw4V9T/AyC+VD9Vg/6kZt2FyvgFzaKiZE68HT0ALCRFfLkkK98xFxPeFEfNgV85cWlxWMlop+0TfwgPzVuH4IyD6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqazAIRYssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20jkBzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwl3Ky2nVgAAgAEAAIACAACAAAAAAAAAAAAhFkMgsL8W8BG1Pqe+YVkkqn8n5dKa0g6hFV2EhnbDutGyOQERXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+HcrLadWAACAAQAAgAEAAIAAAAAAAAAAACEWUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAFAHxGHl0hFvoPejzvOx0MCmzn0m4XraCy5cktGe+tSLQYWcuKRRypOQFvfWIFnpSXoaSiZ1admHbaYBAa/zjjUpubk5zn+RrpcHcrLadWAACAAQAAgAMAAIAAAAAAAAAAAAEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARgg8DYuL3Wm9CClvePrIh2WrmcgzyX4GJDJWx13WstRXmUAAQUgESTaeuySzNBslUViZH9DexOLlXIahL4r8idrvdqz5nEhBxEk2nrskszQbJVFYmR/Q3sTi5VyGoS+K/Ina73as+ZxGQB3Ky2nVgAAgAEAAIAAAACAAAAAAAUAAAAA"
],
"creator" : [
{
diff --git a/test/functional/example_test.py b/test/functional/example_test.py
index 2ad96da854..9cf756060e 100755
--- a/test/functional/example_test.py
+++ b/test/functional/example_test.py
@@ -14,8 +14,15 @@ is testing and *how* it's being tested
from collections import defaultdict
# Avoid wildcard * imports
-from test_framework.blocktools import (create_block, create_coinbase)
-from test_framework.messages import CInv, MSG_BLOCK
+# Use lexicographically sorted multi-line imports
+from test_framework.blocktools import (
+ create_block,
+ create_coinbase,
+)
+from test_framework.messages import (
+ CInv,
+ MSG_BLOCK,
+)
from test_framework.p2p import (
P2PInterface,
msg_block,
diff --git a/test/functional/feature_addrman.py b/test/functional/feature_addrman.py
index 5e49d0214a..63abf0d9f8 100755
--- a/test/functional/feature_addrman.py
+++ b/test/functional/feature_addrman.py
@@ -95,7 +95,7 @@ class AddrmanTest(BitcoinTestFramework):
with open(peers_dat, "wb") as f:
f.write(serialize_addrman()[:-1])
self.nodes[0].assert_start_raises_init_error(
- expected_msg=init_error("CAutoFile::read: end of file.*"),
+ expected_msg=init_error("AutoFile::read: end of file.*"),
match=ErrorMatch.FULL_REGEX,
)
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 462deeae32..850cb8334c 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -1297,7 +1297,7 @@ class FullBlockTest(BitcoinTestFramework):
blocks2 = []
for i in range(89, LARGE_REORG_SIZE + 89):
blocks2.append(self.next_block("alt" + str(i)))
- self.send_blocks(blocks2, False, force_send=True)
+ self.send_blocks(blocks2, False, force_send=False)
# extend alt chain to trigger re-org
block = self.next_block("alt" + str(chain1_tip + 1))
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index 6c51a5ac31..eb31bca29a 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -186,11 +186,12 @@ class ConfArgsTest(BitcoinTestFramework):
with self.nodes[0].assert_debug_log(expected_msgs=[
"Loaded 0 addresses from peers.dat",
"DNS seeding disabled",
- "Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n",
+ "Adding fixed seeds as -dnsseed=0 (or IPv4/IPv6 connections are disabled via -onlynet), -addnode is not provided and all -seednode(s) attempted\n",
]):
self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1'])
assert time.time() - start < 60
self.stop_node(0)
+ self.nodes[0].assert_start_raises_init_error(['-dnsseed=1', '-onlynet=i2p', '-i2psam=127.0.0.1:7656'], "Error: Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")
# No peers.dat exists and dns seeds are disabled.
# We expect the node will not add fixed seeds when explicitly disabled.
diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py
index a3a5e9e27d..f606f26e70 100755
--- a/test/functional/feature_dbcrash.py
+++ b/test/functional/feature_dbcrash.py
@@ -62,8 +62,8 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
self.node2_args = ["-dbcrashratio=24", "-dbcache=16"] + self.base_args
# Node3 is a normal node with default args, except will mine full blocks
- # and non-standard txs (e.g. txs with "dust" outputs)
- self.node3_args = ["-blockmaxweight=4000000", "-acceptnonstdtxn"]
+ # and txs with "dust" outputs
+ self.node3_args = ["-blockmaxweight=4000000", "-dustrelayfee=0"]
self.extra_args = [self.node0_args, self.node1_args, self.node2_args, self.node3_args]
def setup_network(self):
@@ -192,14 +192,12 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
# Sanity check -- if we chose inputs that are too small, skip
continue
- tx = self.wallet.create_self_transfer_multi(
+ self.wallet.send_self_transfer_multi(
from_node=node,
utxos_to_spend=utxos_to_spend,
num_outputs=3,
- fee_per_output=FEE // 3)
-
- # Send the transaction to get into the mempool (skip fee-checks to run faster)
- node.sendrawtransaction(hexstring=tx.serialize().hex(), maxfeerate=0)
+ fee_per_output=FEE // 3,
+ )
num_transactions += 1
def run_test(self):
@@ -213,7 +211,9 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
self.crashed_on_restart = 0 # Track count of crashes during recovery
# Start by creating a lot of utxos on node3
- utxo_list = self.wallet.send_self_transfer_multi(from_node=self.nodes[3], num_outputs=5000)['new_utxos']
+ utxo_list = []
+ for _ in range(5):
+ utxo_list.extend(self.wallet.send_self_transfer_multi(from_node=self.nodes[3], num_outputs=1000)['new_utxos'])
self.generate(self.nodes[3], 1, sync_fun=self.no_op)
assert_equal(len(self.nodes[3].getrawmempool()), 0)
self.log.info(f"Prepped {len(utxo_list)} utxo entries")
diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py
index ca21dd8a73..b0cbcf4edf 100755
--- a/test/functional/feature_fee_estimation.py
+++ b/test/functional/feature_fee_estimation.py
@@ -52,7 +52,8 @@ def small_txpuzzle_randfee(
raise RuntimeError(f"Insufficient funds: need {amount + fee}, have {total_in}")
tx = wallet.create_self_transfer_multi(
utxos_to_spend=utxos_to_spend,
- fee_per_output=0)
+ fee_per_output=0,
+ )["tx"]
tx.vout[0].nValue = int((total_in - amount - fee) * COIN)
tx.vout.append(deepcopy(tx.vout[0]))
tx.vout[1].nValue = int(amount * COIN)
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 0b9d651226..3ea412002a 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -46,7 +46,7 @@ class MaxUploadTest(BitcoinTestFramework):
self.num_nodes = 1
self.extra_args = [[
"-maxuploadtarget=800M",
- "-acceptnonstdtxn=1",
+ "-datacarriersize=100000",
]]
self.supports_cli = False
diff --git a/test/functional/feature_minchainwork.py b/test/functional/feature_minchainwork.py
index fa10855a98..fb4024b1b0 100755
--- a/test/functional/feature_minchainwork.py
+++ b/test/functional/feature_minchainwork.py
@@ -82,7 +82,7 @@ class MinimumChainWorkTest(BitcoinTestFramework):
msg.hashstop = 0
peer.send_and_ping(msg)
time.sleep(5)
- assert "headers" not in peer.last_message
+ assert "headers" not in peer.last_message or len(peer.last_message["headers"].headers) == 0
self.log.info("Generating one more block")
self.generate(self.nodes[0], 1)
diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py
index 7a84098a83..9bfb79057e 100755
--- a/test/functional/feature_nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -19,9 +19,11 @@ from test_framework.blocktools import (
NORMAL_GBT_REQUEST_PARAMS,
add_witness_commitment,
create_block,
- create_transaction,
)
-from test_framework.messages import CTransaction
+from test_framework.messages import (
+ CTransaction,
+ tx_from_hex,
+)
from test_framework.script import (
OP_0,
OP_TRUE,
@@ -31,6 +33,9 @@ from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
)
+from test_framework.wallet import getnewdestination
+from test_framework.key import ECKey
+from test_framework.wallet_util import bytes_to_wif
NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
@@ -55,22 +60,26 @@ class NULLDUMMYTest(BitcoinTestFramework):
'-par=1', # Use only one script thread to get the exact reject reason for testing
]]
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
+ def create_transaction(self, *, txid, input_details=None, addr, amount, privkey):
+ input = {"txid": txid, "vout": 0}
+ output = {addr: amount}
+ rawtx = self.nodes[0].createrawtransaction([input], output)
+ # Details only needed for scripthash or witness spends
+ input = None if not input_details else [{**input, **input_details}]
+ signedtx = self.nodes[0].signrawtransactionwithkey(rawtx, [privkey], input)
+ return tx_from_hex(signedtx["hex"])
def run_test(self):
- self.nodes[0].createwallet(wallet_name='wmulti', disable_private_keys=True)
- wmulti = self.nodes[0].get_wallet_rpc('wmulti')
- w0 = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
- self.address = w0.getnewaddress()
- self.pubkey = w0.getaddressinfo(self.address)['pubkey']
- self.ms_address = wmulti.addmultisigaddress(1, [self.pubkey])['address']
- self.wit_address = w0.getnewaddress(address_type='p2sh-segwit')
- self.wit_ms_address = wmulti.addmultisigaddress(1, [self.pubkey], '', 'p2sh-segwit')['address']
- if not self.options.descriptors:
- # Legacy wallets need to import these so that they are watched by the wallet. This is unnecessary (and does not need to be tested) for descriptor wallets
- wmulti.importaddress(self.ms_address)
- wmulti.importaddress(self.wit_ms_address)
+ eckey = ECKey()
+ eckey.generate()
+ self.privkey = bytes_to_wif(eckey.get_bytes())
+ self.pubkey = eckey.get_pubkey().get_bytes().hex()
+ cms = self.nodes[0].createmultisig(1, [self.pubkey])
+ wms = self.nodes[0].createmultisig(1, [self.pubkey], 'p2sh-segwit')
+ self.ms_address = cms["address"]
+ ms_unlock_details = {"scriptPubKey": self.nodes[0].validateaddress(self.ms_address)["scriptPubKey"],
+ "redeemScript": cms["redeemScript"]}
+ self.wit_ms_address = wms['address']
self.coinbase_blocks = self.generate(self.nodes[0], 2) # block height = 2
coinbase_txid = []
@@ -82,16 +91,23 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.lastblocktime = int(time.time()) + self.lastblockheight
self.log.info(f"Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [{COINBASE_MATURITY + 3}]")
- test1txs = [create_transaction(self.nodes[0], coinbase_txid[0], self.ms_address, amount=49)]
+ test1txs = [self.create_transaction(txid=coinbase_txid[0], addr=self.ms_address, amount=49,
+ privkey=self.nodes[0].get_deterministic_priv_key().key)]
txid1 = self.nodes[0].sendrawtransaction(test1txs[0].serialize_with_witness().hex(), 0)
- test1txs.append(create_transaction(self.nodes[0], txid1, self.ms_address, amount=48))
+ test1txs.append(self.create_transaction(txid=txid1, input_details=ms_unlock_details,
+ addr=self.ms_address, amount=48,
+ privkey=self.privkey))
txid2 = self.nodes[0].sendrawtransaction(test1txs[1].serialize_with_witness().hex(), 0)
- test1txs.append(create_transaction(self.nodes[0], coinbase_txid[1], self.wit_ms_address, amount=49))
+ test1txs.append(self.create_transaction(txid=coinbase_txid[1],
+ addr=self.wit_ms_address, amount=49,
+ privkey=self.nodes[0].get_deterministic_priv_key().key))
txid3 = self.nodes[0].sendrawtransaction(test1txs[2].serialize_with_witness().hex(), 0)
self.block_submit(self.nodes[0], test1txs, accept=True)
self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation")
- test2tx = create_transaction(self.nodes[0], txid2, self.ms_address, amount=47)
+ test2tx = self.create_transaction(txid=txid2, input_details=ms_unlock_details,
+ addr=self.ms_address, amount=47,
+ privkey=self.privkey)
invalidate_nulldummy_tx(test2tx)
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test2tx.serialize_with_witness().hex(), 0)
@@ -99,14 +115,19 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.block_submit(self.nodes[0], [test2tx], accept=True)
self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation")
- test4tx = create_transaction(self.nodes[0], test2tx.hash, self.address, amount=46)
+ test4tx = self.create_transaction(txid=test2tx.hash, input_details=ms_unlock_details,
+ addr=getnewdestination()[2], amount=46,
+ privkey=self.privkey)
test6txs = [CTransaction(test4tx)]
invalidate_nulldummy_tx(test4tx)
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test4tx.serialize_with_witness().hex(), 0)
self.block_submit(self.nodes[0], [test4tx], accept=False)
self.log.info("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation")
- test5tx = create_transaction(self.nodes[0], txid3, self.wit_address, amount=48)
+ test5tx = self.create_transaction(txid=txid3, input_details={"scriptPubKey": test1txs[2].vout[0].scriptPubKey.hex(),
+ "amount": 49, "witnessScript": wms["redeemScript"]},
+ addr=getnewdestination(address_type='p2sh-segwit')[2], amount=48,
+ privkey=self.privkey)
test6txs.append(CTransaction(test5tx))
test5tx.wit.vtxinwit[0].scriptWitness.stack[0] = b'\x01'
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, test5tx.serialize_with_witness().hex(), 0)
diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py
index dd3cdc96ca..c90852562e 100755
--- a/test/functional/feature_proxy.py
+++ b/test/functional/feature_proxy.py
@@ -332,20 +332,37 @@ class ProxyTest(BitcoinTestFramework):
msg = "Error: Invalid -i2psam address or hostname: 'def:xyz'"
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
- msg = (
- "Error: Outbound connections restricted to Tor (-onlynet=onion) but "
- "the proxy for reaching the Tor network is not provided (no -proxy= "
- "and no -onion= given) or it is explicitly forbidden (-onion=0)"
- )
- self.log.info("Test passing -onlynet=onion without -proxy or -onion raises expected init error")
- self.nodes[1].extra_args = ["-onlynet=onion"]
+ self.log.info("Test passing invalid -onlynet=i2p without -i2psam raises expected init error")
+ self.nodes[1].extra_args = ["-onlynet=i2p"]
+ msg = "Error: Outbound connections restricted to i2p (-onlynet=i2p) but -i2psam is not provided"
+ self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
+
+ self.log.info("Test passing invalid -onlynet=cjdns without -cjdnsreachable raises expected init error")
+ self.nodes[1].extra_args = ["-onlynet=cjdns"]
+ msg = "Error: Outbound connections restricted to CJDNS (-onlynet=cjdns) but -cjdnsreachable is not provided"
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
self.log.info("Test passing -onlynet=onion with -onion=0/-noonion raises expected init error")
+ msg = (
+ "Error: Outbound connections restricted to Tor (-onlynet=onion) but "
+ "the proxy for reaching the Tor network is explicitly forbidden: -onion=0"
+ )
for arg in ["-onion=0", "-noonion"]:
self.nodes[1].extra_args = ["-onlynet=onion", arg]
self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
+ self.log.info("Test passing -onlynet=onion without -proxy, -onion or -listenonion raises expected init error")
+ self.nodes[1].extra_args = ["-onlynet=onion", "-listenonion=0"]
+ msg = (
+ "Error: 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"
+ )
+ self.nodes[1].assert_start_raises_init_error(expected_msg=msg)
+
+ self.log.info("Test passing -onlynet=onion without -proxy or -onion but with -listenonion=1 is ok")
+ self.start_node(1, extra_args=["-onlynet=onion", "-listenonion=1"])
+ self.stop_node(1)
+
self.log.info("Test passing unknown network to -onlynet raises expected init error")
self.nodes[1].extra_args = ["-onlynet=abc"]
msg = "Error: Unknown network specified in -onlynet: 'abc'"
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index 738c6ea4af..7603248ae5 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -4,28 +4,18 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the RBF code."""
-from copy import deepcopy
from decimal import Decimal
from test_framework.messages import (
- BIP125_SEQUENCE_NUMBER,
+ MAX_BIP125_RBF_SEQUENCE,
COIN,
- COutPoint,
- CTransaction,
- CTxIn,
- CTxOut,
SEQUENCE_FINAL,
)
-from test_framework.script import CScript, OP_DROP
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
)
-from test_framework.script_util import (
- DUMMY_P2WPKH_SCRIPT,
- DUMMY_2_P2WPKH_SCRIPT,
-)
from test_framework.wallet import MiniWallet
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
@@ -35,7 +25,6 @@ class ReplaceByFeeTest(BitcoinTestFramework):
self.num_nodes = 2
self.extra_args = [
[
- "-acceptnonstdtxn=1",
"-maxorphantx=1000",
"-limitancestorcount=50",
"-limitancestorsize=101",
@@ -94,17 +83,19 @@ class ReplaceByFeeTest(BitcoinTestFramework):
self.log.info("Running test replacement relay fee...")
self.test_replacement_relay_fee()
+ self.log.info("Running test full replace by fee...")
+ self.test_fullrbf()
+
self.log.info("Passed")
- def make_utxo(self, node, amount, confirmed=True, scriptPubKey=DUMMY_P2WPKH_SCRIPT):
+ def make_utxo(self, node, amount, *, confirmed=True, scriptPubKey=None):
"""Create a txout with a given amount and scriptPubKey
- confirmed - txouts created will be confirmed in the blockchain;
+ confirmed - txout created will be confirmed in the blockchain;
unconfirmed otherwise.
"""
- txid, n = self.wallet.send_to(from_node=node, scriptPubKey=scriptPubKey, amount=amount)
+ txid, n = self.wallet.send_to(from_node=node, scriptPubKey=scriptPubKey or self.wallet.get_scriptPubKey(), amount=amount)
- # If requested, ensure txouts are confirmed.
if confirmed:
mempool_size = len(node.getrawmempool())
while mempool_size > 0:
@@ -115,30 +106,24 @@ class ReplaceByFeeTest(BitcoinTestFramework):
assert new_size < mempool_size
mempool_size = new_size
- return COutPoint(int(txid, 16), n)
+ return self.wallet.get_utxo(txid=txid, vout=n)
def test_simple_doublespend(self):
"""Simple doublespend"""
# we use MiniWallet to create a transaction template with inputs correctly set,
# and modify the output (amount, scriptPubKey) according to our needs
- tx_template = self.wallet.create_self_transfer()['tx']
-
- tx1a = deepcopy(tx_template)
- tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)]
- tx1a_hex = tx1a.serialize().hex()
- tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0)
+ tx = self.wallet.create_self_transfer()["tx"]
+ tx1a_txid = self.nodes[0].sendrawtransaction(tx.serialize().hex())
# Should fail because we haven't changed the fee
- tx1b = deepcopy(tx_template)
- tx1b.vout = [CTxOut(1 * COIN, DUMMY_2_P2WPKH_SCRIPT)]
- tx1b_hex = tx1b.serialize().hex()
+ tx.vout[0].scriptPubKey[-1] ^= 1
# This will raise an exception due to insufficient fee
- assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, 0)
+ assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx.serialize().hex(), 0)
# Extra 0.1 BTC fee
- tx1b.vout[0].nValue -= int(0.1 * COIN)
- tx1b_hex = tx1b.serialize().hex()
+ tx.vout[0].nValue -= int(0.1 * COIN)
+ tx1b_hex = tx.serialize().hex()
# Works when enabled
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0)
@@ -160,28 +145,28 @@ class ReplaceByFeeTest(BitcoinTestFramework):
chain_txids = []
while remaining_value > 1 * COIN:
remaining_value -= int(0.1 * COIN)
- tx = CTransaction()
- tx.vin = [CTxIn(prevout, nSequence=0)]
- tx.vout = [CTxOut(remaining_value, CScript([1, OP_DROP] * 15 + [1]))]
- tx_hex = tx.serialize().hex()
- txid = self.nodes[0].sendrawtransaction(tx_hex, 0)
- chain_txids.append(txid)
- prevout = COutPoint(int(txid, 16), 0)
+ prevout = self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=prevout,
+ sequence=0,
+ fee=Decimal("0.1"),
+ )["new_utxo"]
+ chain_txids.append(prevout["txid"])
# Whether the double-spend is allowed is evaluated by including all
# child fees - 4 BTC - so this attempt is rejected.
- dbl_tx = CTransaction()
- dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - 3 * COIN, DUMMY_P2WPKH_SCRIPT)]
+ dbl_tx = self.wallet.create_self_transfer(
+ utxo_to_spend=tx0_outpoint,
+ sequence=0,
+ fee=Decimal("3"),
+ )["tx"]
dbl_tx_hex = dbl_tx.serialize().hex()
# This will raise an exception due to insufficient fee
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0)
# Accepted with sufficient fee
- dbl_tx = CTransaction()
- dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(int(0.1 * COIN), DUMMY_P2WPKH_SCRIPT)]
+ dbl_tx.vout[0].nValue = int(0.1 * COIN)
dbl_tx_hex = dbl_tx.serialize().hex()
self.nodes[0].sendrawtransaction(dbl_tx_hex, 0)
@@ -205,22 +190,19 @@ class ReplaceByFeeTest(BitcoinTestFramework):
if txout_value < fee:
return
- vout = [CTxOut(txout_value, CScript([i+1]))
- for i in range(tree_width)]
- tx = CTransaction()
- tx.vin = [CTxIn(prevout, nSequence=0)]
- tx.vout = vout
- tx_hex = tx.serialize().hex()
+ tx = self.wallet.send_self_transfer_multi(
+ utxos_to_spend=[prevout],
+ from_node=self.nodes[0],
+ sequence=0,
+ num_outputs=tree_width,
+ amount_per_output=txout_value,
+ )
- assert len(tx.serialize()) < 100000
- txid = self.nodes[0].sendrawtransaction(tx_hex, 0)
- yield tx
+ yield tx["txid"]
_total_txs[0] += 1
- txid = int(txid, 16)
-
- for i, txout in enumerate(tx.vout):
- for x in branch(COutPoint(txid, i), txout_value,
+ for utxo in tx["new_utxos"]:
+ for x in branch(utxo, txout_value,
max_txs,
tree_width=tree_width, fee=fee,
_total_txs=_total_txs):
@@ -232,25 +214,26 @@ class ReplaceByFeeTest(BitcoinTestFramework):
assert_equal(len(tree_txs), n)
# Attempt double-spend, will fail because too little fee paid
- dbl_tx = CTransaction()
- dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - fee * n, DUMMY_P2WPKH_SCRIPT)]
- dbl_tx_hex = dbl_tx.serialize().hex()
+ dbl_tx_hex = self.wallet.create_self_transfer(
+ utxo_to_spend=tx0_outpoint,
+ sequence=0,
+ fee=(Decimal(fee) / COIN) * n,
+ )["hex"]
# This will raise an exception due to insufficient fee
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0)
# 0.1 BTC fee is enough
- dbl_tx = CTransaction()
- dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - fee * n - int(0.1 * COIN), DUMMY_P2WPKH_SCRIPT)]
- dbl_tx_hex = dbl_tx.serialize().hex()
+ dbl_tx_hex = self.wallet.create_self_transfer(
+ utxo_to_spend=tx0_outpoint,
+ sequence=0,
+ fee=(Decimal(fee) / COIN) * n + Decimal("0.1"),
+ )["hex"]
self.nodes[0].sendrawtransaction(dbl_tx_hex, 0)
mempool = self.nodes[0].getrawmempool()
- for tx in tree_txs:
- tx.rehash()
- assert tx.hash not in mempool
+ for txid in tree_txs:
+ assert txid not in mempool
# Try again, but with more total transactions than the "max txs
# double-spent at once" anti-DoS limit.
@@ -260,33 +243,36 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
assert_equal(len(tree_txs), n)
- dbl_tx = CTransaction()
- dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, DUMMY_P2WPKH_SCRIPT)]
- dbl_tx_hex = dbl_tx.serialize().hex()
+ dbl_tx_hex = self.wallet.create_self_transfer(
+ utxo_to_spend=tx0_outpoint,
+ sequence=0,
+ fee=2 * (Decimal(fee) / COIN) * n,
+ )["hex"]
# This will raise an exception
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0)
- for tx in tree_txs:
- tx.rehash()
- self.nodes[0].getrawtransaction(tx.hash)
+ for txid in tree_txs:
+ self.nodes[0].getrawtransaction(txid)
def test_replacement_feeperkb(self):
"""Replacement requires fee-per-KB to be higher"""
tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN))
- tx1a = CTransaction()
- tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)]
- tx1a_hex = tx1a.serialize().hex()
- self.nodes[0].sendrawtransaction(tx1a_hex, 0)
+ self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=tx0_outpoint,
+ sequence=0,
+ fee=Decimal("0.1"),
+ )
# Higher fee, but the fee per KB is much lower, so the replacement is
# rejected.
- tx1b = CTransaction()
- tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(int(0.001 * COIN), CScript([b'a' * 999000]))]
- tx1b_hex = tx1b.serialize().hex()
+ tx1b_hex = self.wallet.create_self_transfer_multi(
+ utxos_to_spend=[tx0_outpoint],
+ sequence=0,
+ num_outputs=100,
+ amount_per_output=1000,
+ )["hex"]
# This will raise an exception due to insufficient fee
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, 0)
@@ -296,37 +282,36 @@ class ReplaceByFeeTest(BitcoinTestFramework):
utxo1 = self.make_utxo(self.nodes[0], int(1.2 * COIN))
utxo2 = self.make_utxo(self.nodes[0], 3 * COIN)
- tx1a = CTransaction()
- tx1a.vin = [CTxIn(utxo1, nSequence=0)]
- tx1a.vout = [CTxOut(int(1.1 * COIN), DUMMY_P2WPKH_SCRIPT)]
- tx1a_hex = tx1a.serialize().hex()
- tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0)
-
- tx1a_txid = int(tx1a_txid, 16)
+ tx1a_utxo = self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=utxo1,
+ sequence=0,
+ fee=Decimal("0.1"),
+ )["new_utxo"]
# Direct spend an output of the transaction we're replacing.
- tx2 = CTransaction()
- tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0)]
- tx2.vin.append(CTxIn(COutPoint(tx1a_txid, 0), nSequence=0))
- tx2.vout = tx1a.vout
- tx2_hex = tx2.serialize().hex()
+ tx2_hex = self.wallet.create_self_transfer_multi(
+ utxos_to_spend=[utxo1, utxo2, tx1a_utxo],
+ sequence=0,
+ amount_per_output=int(COIN * tx1a_utxo["value"]),
+ )["hex"]
# This will raise an exception
assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, 0)
# Spend tx1a's output to test the indirect case.
- tx1b = CTransaction()
- tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
- tx1b.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)]
- tx1b_hex = tx1b.serialize().hex()
- tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0)
- tx1b_txid = int(tx1b_txid, 16)
+ tx1b_utxo = self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=tx1a_utxo,
+ sequence=0,
+ fee=Decimal("0.1"),
+ )["new_utxo"]
- tx2 = CTransaction()
- tx2.vin = [CTxIn(utxo1, nSequence=0), CTxIn(utxo2, nSequence=0),
- CTxIn(COutPoint(tx1b_txid, 0))]
- tx2.vout = tx1a.vout
- tx2_hex = tx2.serialize().hex()
+ tx2_hex = self.wallet.create_self_transfer_multi(
+ utxos_to_spend=[utxo1, utxo2, tx1b_utxo],
+ sequence=0,
+ amount_per_output=int(COIN * tx1a_utxo["value"]),
+ )["hex"]
# This will raise an exception
assert_raises_rpc_error(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, 0)
@@ -334,18 +319,20 @@ class ReplaceByFeeTest(BitcoinTestFramework):
def test_new_unconfirmed_inputs(self):
"""Replacements that add new unconfirmed inputs are rejected"""
confirmed_utxo = self.make_utxo(self.nodes[0], int(1.1 * COIN))
- unconfirmed_utxo = self.make_utxo(self.nodes[0], int(0.1 * COIN), False)
+ unconfirmed_utxo = self.make_utxo(self.nodes[0], int(0.1 * COIN), confirmed=False)
- tx1 = CTransaction()
- tx1.vin = [CTxIn(confirmed_utxo)]
- tx1.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)]
- tx1_hex = tx1.serialize().hex()
- self.nodes[0].sendrawtransaction(tx1_hex, 0)
+ self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=confirmed_utxo,
+ sequence=0,
+ fee=Decimal("0.1"),
+ )
- tx2 = CTransaction()
- tx2.vin = [CTxIn(confirmed_utxo), CTxIn(unconfirmed_utxo)]
- tx2.vout = tx1.vout
- tx2_hex = tx2.serialize().hex()
+ tx2_hex = self.wallet.create_self_transfer_multi(
+ utxos_to_spend=[confirmed_utxo, unconfirmed_utxo],
+ sequence=0,
+ amount_per_output=1 * COIN,
+ )["hex"]
# This will raise an exception
assert_raises_rpc_error(-26, "replacement-adds-unconfirmed", self.nodes[0].sendrawtransaction, tx2_hex, 0)
@@ -361,51 +348,45 @@ class ReplaceByFeeTest(BitcoinTestFramework):
fee = int(0.0001 * COIN)
split_value = int((initial_nValue - fee) / (MAX_REPLACEMENT_LIMIT + 1))
- outputs = []
- for _ in range(MAX_REPLACEMENT_LIMIT + 1):
- outputs.append(CTxOut(split_value, CScript([1])))
-
- splitting_tx = CTransaction()
- splitting_tx.vin = [CTxIn(utxo, nSequence=0)]
- splitting_tx.vout = outputs
- splitting_tx_hex = splitting_tx.serialize().hex()
-
- txid = self.nodes[0].sendrawtransaction(splitting_tx_hex, 0)
- txid = int(txid, 16)
+ splitting_tx_utxos = self.wallet.send_self_transfer_multi(
+ from_node=self.nodes[0],
+ utxos_to_spend=[utxo],
+ sequence=0,
+ num_outputs=MAX_REPLACEMENT_LIMIT + 1,
+ amount_per_output=split_value,
+ )["new_utxos"]
# Now spend each of those outputs individually
- for i in range(MAX_REPLACEMENT_LIMIT + 1):
- tx_i = CTransaction()
- tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
- tx_i.vout = [CTxOut(split_value - fee, DUMMY_P2WPKH_SCRIPT)]
- tx_i_hex = tx_i.serialize().hex()
- self.nodes[0].sendrawtransaction(tx_i_hex, 0)
+ for utxo in splitting_tx_utxos:
+ self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=utxo,
+ sequence=0,
+ fee=Decimal(fee) / COIN,
+ )
# Now create doublespend of the whole lot; should fail.
# Need a big enough fee to cover all spending transactions and have
# a higher fee rate
double_spend_value = (split_value - 100 * fee) * (MAX_REPLACEMENT_LIMIT + 1)
- inputs = []
- for i in range(MAX_REPLACEMENT_LIMIT + 1):
- inputs.append(CTxIn(COutPoint(txid, i), nSequence=0))
- double_tx = CTransaction()
- double_tx.vin = inputs
- double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
+ double_tx = self.wallet.create_self_transfer_multi(
+ utxos_to_spend=splitting_tx_utxos,
+ sequence=0,
+ amount_per_output=double_spend_value,
+ )["tx"]
double_tx_hex = double_tx.serialize().hex()
# This will raise an exception
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, 0)
# If we remove an input, it should pass
- double_tx = CTransaction()
- double_tx.vin = inputs[0:-1]
- double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))]
+ double_tx.vin.pop()
double_tx_hex = double_tx.serialize().hex()
self.nodes[0].sendrawtransaction(double_tx_hex, 0)
def test_too_many_replacements_with_default_mempool_params(self):
"""
- Test rule 5 of BIP125 (do not allow replacements that cause more than 100
+ Test rule 5 (do not allow replacements that cause more than 100
evictions) without having to rely on non-default mempool parameters.
In order to do this, create a number of "root" UTXOs, and then hang
@@ -424,7 +405,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# limit; 10 works.
num_tx_graphs = 10
- # (Number of transactions per graph, BIP125 rule 5 failure expected)
+ # (Number of transactions per graph, rule 5 failure expected)
cases = [
# Test the base case of evicting fewer than MAX_REPLACEMENT_LIMIT
# transactions.
@@ -447,7 +428,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
optin_parent_tx = wallet.send_self_transfer_multi(
from_node=normal_node,
- sequence=BIP125_SEQUENCE_NUMBER,
+ sequence=MAX_BIP125_RBF_SEQUENCE,
utxos_to_spend=[root_utxos[graph_num]],
num_outputs=txs_per_graph,
)
@@ -472,11 +453,10 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Now attempt to submit a tx that double-spends all the root tx inputs, which
# would invalidate `num_txs_invalidated` transactions.
- double_tx = wallet.create_self_transfer_multi(
+ tx_hex = wallet.create_self_transfer_multi(
utxos_to_spend=root_utxos,
fee_per_output=10_000_000, # absurdly high feerate
- )
- tx_hex = double_tx.serialize().hex()
+ )["hex"]
if failure_expected:
assert_raises_rpc_error(
@@ -495,20 +475,22 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN))
# Create a non-opting in transaction
- tx1a = CTransaction()
- tx1a.vin = [CTxIn(tx0_outpoint, nSequence=SEQUENCE_FINAL)]
- tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)]
- tx1a_hex = tx1a.serialize().hex()
- tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0)
+ tx1a_utxo = self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=tx0_outpoint,
+ sequence=SEQUENCE_FINAL,
+ fee=Decimal("0.1"),
+ )["new_utxo"]
# This transaction isn't shown as replaceable
- assert_equal(self.nodes[0].getmempoolentry(tx1a_txid)['bip125-replaceable'], False)
+ assert_equal(self.nodes[0].getmempoolentry(tx1a_utxo["txid"])['bip125-replaceable'], False)
# Shouldn't be able to double-spend
- tx1b = CTransaction()
- tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(int(0.9 * COIN), DUMMY_P2WPKH_SCRIPT)]
- tx1b_hex = tx1b.serialize().hex()
+ tx1b_hex = self.wallet.create_self_transfer(
+ utxo_to_spend=tx0_outpoint,
+ sequence=0,
+ fee=Decimal("0.2"),
+ )["hex"]
# This will raise an exception
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, 0)
@@ -516,17 +498,19 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN))
# Create a different non-opting in transaction
- tx2a = CTransaction()
- tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
- tx2a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)]
- tx2a_hex = tx2a.serialize().hex()
- tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, 0)
+ tx2a_utxo = self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=tx1_outpoint,
+ sequence=0xfffffffe,
+ fee=Decimal("0.1"),
+ )["new_utxo"]
# Still shouldn't be able to double-spend
- tx2b = CTransaction()
- tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2b.vout = [CTxOut(int(0.9 * COIN), DUMMY_P2WPKH_SCRIPT)]
- tx2b_hex = tx2b.serialize().hex()
+ tx2b_hex = self.wallet.create_self_transfer(
+ utxo_to_spend=tx1_outpoint,
+ sequence=0,
+ fee=Decimal("0.2"),
+ )["hex"]
# This will raise an exception
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx2b_hex, 0)
@@ -535,34 +519,31 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# opt-in on one of the inputs
# Transaction should be replaceable on either input
- tx1a_txid = int(tx1a_txid, 16)
- tx2a_txid = int(tx2a_txid, 16)
-
- tx3a = CTransaction()
- tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=SEQUENCE_FINAL),
- CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)]
- tx3a.vout = [CTxOut(int(0.9 * COIN), CScript([b'c'])), CTxOut(int(0.9 * COIN), CScript([b'd']))]
- tx3a_hex = tx3a.serialize().hex()
-
- tx3a_txid = self.nodes[0].sendrawtransaction(tx3a_hex, 0)
+ tx3a_txid = self.wallet.send_self_transfer_multi(
+ from_node=self.nodes[0],
+ utxos_to_spend=[tx1a_utxo, tx2a_utxo],
+ sequence=[SEQUENCE_FINAL, 0xfffffffd],
+ fee_per_output=int(0.1 * COIN),
+ )["txid"]
# This transaction is shown as replaceable
assert_equal(self.nodes[0].getmempoolentry(tx3a_txid)['bip125-replaceable'], True)
- tx3b = CTransaction()
- tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
- tx3b.vout = [CTxOut(int(0.5 * COIN), DUMMY_P2WPKH_SCRIPT)]
- tx3b_hex = tx3b.serialize().hex()
-
- tx3c = CTransaction()
- tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
- tx3c.vout = [CTxOut(int(0.5 * COIN), DUMMY_P2WPKH_SCRIPT)]
- tx3c_hex = tx3c.serialize().hex()
+ self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=tx1a_utxo,
+ sequence=0,
+ fee=Decimal("0.4"),
+ )
- self.nodes[0].sendrawtransaction(tx3b_hex, 0)
# If tx3b was accepted, tx3c won't look like a replacement,
# but make sure it is accepted anyway
- self.nodes[0].sendrawtransaction(tx3c_hex, 0)
+ self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=tx2a_utxo,
+ sequence=0,
+ fee=Decimal("0.4"),
+ )
def test_prioritised_transactions(self):
# Ensure that fee deltas used via prioritisetransaction are
@@ -571,17 +552,20 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# 1. Check that feeperkb uses modified fees
tx0_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN))
- tx1a = CTransaction()
- tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)]
- tx1a_hex = tx1a.serialize().hex()
- tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0)
+ tx1a_txid = self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=tx0_outpoint,
+ sequence=0,
+ fee=Decimal("0.1"),
+ )["txid"]
# Higher fee, but the actual fee per KB is much lower.
- tx1b = CTransaction()
- tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(int(0.001 * COIN), CScript([b'a' * 740000]))]
- tx1b_hex = tx1b.serialize().hex()
+ tx1b_hex = self.wallet.create_self_transfer_multi(
+ utxos_to_spend=[tx0_outpoint],
+ sequence=0,
+ num_outputs=100,
+ amount_per_output=int(0.00001 * COIN),
+ )["hex"]
# Verify tx1b cannot replace tx1a.
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, 0)
@@ -597,27 +581,29 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# 2. Check that absolute fee checks use modified fee.
tx1_outpoint = self.make_utxo(self.nodes[0], int(1.1 * COIN))
- tx2a = CTransaction()
- tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)]
- tx2a_hex = tx2a.serialize().hex()
- self.nodes[0].sendrawtransaction(tx2a_hex, 0)
+ # tx2a
+ self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=tx1_outpoint,
+ sequence=0,
+ fee=Decimal("0.1"),
+ )
# Lower fee, but we'll prioritise it
- tx2b = CTransaction()
- tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2b.vout = [CTxOut(int(1.01 * COIN), DUMMY_P2WPKH_SCRIPT)]
- tx2b.rehash()
- tx2b_hex = tx2b.serialize().hex()
+ tx2b = self.wallet.create_self_transfer(
+ utxo_to_spend=tx1_outpoint,
+ sequence=0,
+ fee=Decimal("0.09"),
+ )
# Verify tx2b cannot replace tx2a.
- assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, 0)
+ assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b["hex"], 0)
# Now prioritise tx2b to have a higher modified fee
- self.nodes[0].prioritisetransaction(txid=tx2b.hash, fee_delta=int(0.1 * COIN))
+ self.nodes[0].prioritisetransaction(txid=tx2b["txid"], fee_delta=int(0.1 * COIN))
# tx2b should now be accepted
- tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, 0)
+ tx2b_txid = self.nodes[0].sendrawtransaction(tx2b["hex"], 0)
assert tx2b_txid in self.nodes[0].getrawmempool()
@@ -650,14 +636,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
optin_parent_tx = self.wallet.send_self_transfer(
from_node=self.nodes[0],
utxo_to_spend=confirmed_utxo,
- sequence=BIP125_SEQUENCE_NUMBER,
+ sequence=MAX_BIP125_RBF_SEQUENCE,
fee_rate=Decimal('0.01'),
)
assert_equal(True, self.nodes[0].getmempoolentry(optin_parent_tx['txid'])['bip125-replaceable'])
replacement_parent_tx = self.wallet.create_self_transfer(
utxo_to_spend=confirmed_utxo,
- sequence=BIP125_SEQUENCE_NUMBER,
+ sequence=MAX_BIP125_RBF_SEQUENCE,
fee_rate=Decimal('0.02'),
)
@@ -711,8 +697,37 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Higher fee, higher feerate, different txid, but the replacement does not provide a relay
# fee conforming to node's `incrementalrelayfee` policy of 1000 sat per KB.
+ assert_equal(self.nodes[0].getmempoolinfo()["incrementalrelayfee"], Decimal("0.00001"))
tx.vout[0].nValue -= 1
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx.serialize().hex())
+ def test_fullrbf(self):
+
+ confirmed_utxo = self.make_utxo(self.nodes[0], int(2 * COIN))
+ self.restart_node(0, extra_args=["-mempoolfullrbf=1"])
+ assert self.nodes[0].getmempoolinfo()["fullrbf"]
+
+ # Create an explicitly opt-out transaction
+ optout_tx = self.wallet.send_self_transfer(
+ from_node=self.nodes[0],
+ utxo_to_spend=confirmed_utxo,
+ sequence=MAX_BIP125_RBF_SEQUENCE + 1,
+ fee_rate=Decimal('0.01'),
+ )
+ assert_equal(False, self.nodes[0].getmempoolentry(optout_tx['txid'])['bip125-replaceable'])
+
+ conflicting_tx = self.wallet.create_self_transfer(
+ utxo_to_spend=confirmed_utxo,
+ sequence=SEQUENCE_FINAL,
+ fee_rate=Decimal('0.02'),
+ )
+
+ # Send the replacement transaction, conflicting with the optout_tx.
+ self.nodes[0].sendrawtransaction(conflicting_tx['hex'], 0)
+
+ # Optout_tx is not anymore in the mempool.
+ assert optout_tx['txid'] not in self.nodes[0].getrawmempool()
+ assert conflicting_tx['txid'] in self.nodes[0].getrawmempool()
+
if __name__ == '__main__':
ReplaceByFeeTest().main()
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index f0faf1421b..7f2a615be1 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -609,6 +609,11 @@ class SegWitTest(BitcoinTestFramework):
assert_equal(self.nodes[1].gettransaction(txid, True)["txid"], txid)
assert_equal(self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid)
+ self.log.info('Test negative and unknown rpcserialversion throw an init error')
+ self.stop_node(0)
+ self.nodes[0].assert_start_raises_init_error(["-rpcserialversion=-1"], "Error: rpcserialversion must be non-negative.")
+ self.nodes[0].assert_start_raises_init_error(["-rpcserialversion=100"], "Error: Unknown rpcserialversion requested.")
+
def mine_and_test_listunspent(self, script_list, ismine):
utxo = find_spendable_utxo(self.nodes[0], 50)
tx = CTransaction()
diff --git a/test/functional/feature_signet.py b/test/functional/feature_signet.py
index 6578caee3f..4c1e48af6d 100755
--- a/test/functional/feature_signet.py
+++ b/test/functional/feature_signet.py
@@ -39,6 +39,14 @@ class SignetBasicTest(BitcoinTestFramework):
shared_args3, shared_args3,
]
+ def setup_network(self):
+ self.setup_nodes()
+
+ # Setup the three signets, which are incompatible with each other
+ self.connect_nodes(0, 1)
+ self.connect_nodes(2, 3)
+ self.connect_nodes(4, 5)
+
def run_test(self):
self.log.info("basic tests using OP_TRUE challenge")
diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py
index 0e44038196..67cdc5ca32 100755
--- a/test/functional/feature_taproot.py
+++ b/test/functional/feature_taproot.py
@@ -91,7 +91,11 @@ from test_framework.script_util import (
script_to_p2wsh_script,
)
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_raises_rpc_error, assert_equal
+from test_framework.util import (
+ assert_raises_rpc_error,
+ assert_equal,
+ random_bytes,
+)
from test_framework.key import generate_privkey, compute_xonly_pubkey, sign_schnorr, tweak_add_privkey, ECKey
from test_framework.address import (
hash160,
@@ -566,10 +570,6 @@ def random_checksig_style(pubkey):
ret = CScript([pubkey, opcode])
return bytes(ret)
-def random_bytes(n):
- """Return a random bytes object of length n."""
- return bytes(random.getrandbits(8) for i in range(n))
-
def bitflipper(expr):
"""Return a callable that evaluates expr and returns it with a random bitflip."""
def fn(ctx):
@@ -1131,6 +1131,12 @@ def spenders_taproot_active():
tap = taproot_construct(pubs[0], scripts)
add_spender(spenders, "alwaysvalid/notsuccessx", tap=tap, leaf="op_success", inputs=[], standard=False, failure={"leaf": "normal"}) # err_msg differs based on opcode
+ # == Test case for https://github.com/bitcoin/bitcoin/issues/24765 ==
+
+ zero_fn = lambda h: bytes([0 for _ in range(32)])
+ tap = taproot_construct(pubs[0], [("leaf", CScript([pubs[1], OP_CHECKSIG, pubs[1], OP_CHECKSIGADD, OP_2, OP_EQUAL])), zero_fn])
+ add_spender(spenders, "case24765", tap=tap, leaf="leaf", inputs=[getter("sign"), getter("sign")], key=secs[1], no_fail=True)
+
# == Legacy tests ==
# Also add a few legacy spends into the mix, so that transactions which combine taproot and pre-taproot spends get tested too.
diff --git a/test/functional/interface_usdt_net.py b/test/functional/interface_usdt_net.py
index 9522cd8c59..2235da702b 100755
--- a/test/functional/interface_usdt_net.py
+++ b/test/functional/interface_usdt_net.py
@@ -109,7 +109,7 @@ class NetTracepointTest(BitcoinTestFramework):
self.log.info(
"hook into the net:inbound_message and net:outbound_message tracepoints")
- ctx = USDT(path=str(self.options.bitcoind))
+ ctx = USDT(pid=self.nodes[0].process.pid)
ctx.enable_probe(probe="net:inbound_message",
fn_name="trace_inbound_message")
ctx.enable_probe(probe="net:outbound_message",
diff --git a/test/functional/interface_usdt_utxocache.py b/test/functional/interface_usdt_utxocache.py
index 0c7f351e66..2280de1479 100755
--- a/test/functional/interface_usdt_utxocache.py
+++ b/test/functional/interface_usdt_utxocache.py
@@ -169,12 +169,11 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
# Create a transaction and invalidate it by changing the txid of the previous
# output to the coinbase txid of the block at height 1.
- invalid_tx = self.wallet.create_self_transfer(
- from_node=self.nodes[0])["tx"]
+ invalid_tx = self.wallet.create_self_transfer()["tx"]
invalid_tx.vin[0].prevout.hash = int(block_1_coinbase_txid, 16)
self.log.info("hooking into the utxocache:uncache tracepoint")
- ctx = USDT(path=str(self.options.bitcoind))
+ ctx = USDT(pid=self.nodes[0].process.pid)
ctx.enable_probe(probe="utxocache:uncache",
fn_name="trace_utxocache_uncache")
bpf = BPF(text=utxocache_changes_program, usdt_contexts=[ctx], debug=0)
@@ -239,7 +238,7 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
self.log.info(
"hook into the utxocache:add and utxocache:spent tracepoints")
- ctx = USDT(path=str(self.options.bitcoind))
+ ctx = USDT(pid=self.nodes[0].process.pid)
ctx.enable_probe(probe="utxocache:add", fn_name="trace_utxocache_add")
ctx.enable_probe(probe="utxocache:spent",
fn_name="trace_utxocache_spent")
@@ -335,7 +334,7 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
self.log.info("test the utxocache:flush tracepoint API")
self.log.info("hook into the utxocache:flush tracepoint")
- ctx = USDT(path=str(self.options.bitcoind))
+ ctx = USDT(pid=self.nodes[0].process.pid)
ctx.enable_probe(probe="utxocache:flush",
fn_name="trace_utxocache_flush")
bpf = BPF(text=utxocache_flushes_program, usdt_contexts=[ctx], debug=0)
@@ -346,16 +345,17 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
# that the handle_* functions succeeded.
EXPECTED_HANDLE_FLUSH_SUCCESS = 3
handle_flush_succeeds = 0
- possible_cache_sizes = set()
- expected_flushes = []
+ expected_flushes = list()
def handle_utxocache_flush(_, data, __):
nonlocal handle_flush_succeeds
event = ctypes.cast(data, ctypes.POINTER(UTXOCacheFlush)).contents
self.log.info(f"handle_utxocache_flush(): {event}")
- expected = expected_flushes.pop(0)
- assert_equal(expected["mode"], FLUSHMODE_NAME[event.mode])
- possible_cache_sizes.remove(event.size) # fails if size not in set
+ expected_flushes.remove({
+ "mode": FLUSHMODE_NAME[event.mode],
+ "for_prune": event.for_prune,
+ "size": event.size
+ })
# sanity checks only
assert(event.memory > 0)
assert(event.duration > 0)
@@ -364,20 +364,19 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
bpf["utxocache_flush"].open_perf_buffer(handle_utxocache_flush)
self.log.info("stop the node to flush the UTXO cache")
- UTXOS_IN_CACHE = 104 # might need to be changed if the eariler tests are modified
+ UTXOS_IN_CACHE = 2 # might need to be changed if the eariler tests are modified
# A node shutdown causes two flushes. One that flushes UTXOS_IN_CACHE
# UTXOs and one that flushes 0 UTXOs. Normally the 0-UTXO-flush is the
# second flush, however it can happen that the order changes.
- possible_cache_sizes = {UTXOS_IN_CACHE, 0}
- flush_for_shutdown = {"mode": "ALWAYS", "for_prune": False}
- expected_flushes.extend([flush_for_shutdown, flush_for_shutdown])
+ expected_flushes.append({"mode": "ALWAYS", "for_prune": False, "size": UTXOS_IN_CACHE})
+ expected_flushes.append({"mode": "ALWAYS", "for_prune": False, "size": 0})
self.stop_node(0)
bpf.perf_buffer_poll(timeout=200)
+ bpf.cleanup()
self.log.info("check that we don't expect additional flushes")
assert_equal(0, len(expected_flushes))
- assert_equal(0, len(possible_cache_sizes))
self.log.info("restart the node with -prune")
self.start_node(0, ["-fastprune=1", "-prune=1"])
@@ -385,12 +384,17 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
BLOCKS_TO_MINE = 350
self.log.info(f"mine {BLOCKS_TO_MINE} blocks to be able to prune")
self.generate(self.wallet, BLOCKS_TO_MINE)
- # we added BLOCKS_TO_MINE coinbase UTXOs to the cache
- possible_cache_sizes = {BLOCKS_TO_MINE}
- expected_flushes.append(
- {"mode": "NONE", "for_prune": True, "size_fn": lambda x: x == BLOCKS_TO_MINE})
+
+ self.log.info("test the utxocache:flush tracepoint API with pruning")
+ self.log.info("hook into the utxocache:flush tracepoint")
+ ctx = USDT(pid=self.nodes[0].process.pid)
+ ctx.enable_probe(probe="utxocache:flush",
+ fn_name="trace_utxocache_flush")
+ bpf = BPF(text=utxocache_flushes_program, usdt_contexts=[ctx], debug=0)
+ bpf["utxocache_flush"].open_perf_buffer(handle_utxocache_flush)
self.log.info(f"prune blockchain to trigger a flush for pruning")
+ expected_flushes.append({"mode": "NONE", "for_prune": True, "size": 0})
self.nodes[0].pruneblockchain(315)
bpf.perf_buffer_poll(timeout=500)
@@ -399,7 +403,6 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
self.log.info(
f"check that we don't expect additional flushes and that the handle_* function succeeded")
assert_equal(0, len(expected_flushes))
- assert_equal(0, len(possible_cache_sizes))
assert_equal(EXPECTED_HANDLE_FLUSH_SUCCESS, handle_flush_succeeds)
diff --git a/test/functional/interface_usdt_validation.py b/test/functional/interface_usdt_validation.py
index d11809273b..8953dd023b 100755
--- a/test/functional/interface_usdt_validation.py
+++ b/test/functional/interface_usdt_validation.py
@@ -91,10 +91,10 @@ class ValidationTracepointTest(BitcoinTestFramework):
# that the handle_* functions succeeded.
BLOCKS_EXPECTED = 2
blocks_checked = 0
- expected_blocks = list()
+ expected_blocks = dict()
self.log.info("hook into the validation:block_connected tracepoint")
- ctx = USDT(path=str(self.options.bitcoind))
+ ctx = USDT(pid=self.nodes[0].process.pid)
ctx.enable_probe(probe="validation:block_connected",
fn_name="trace_block_connected")
bpf = BPF(text=validation_blockconnected_program,
@@ -104,15 +104,16 @@ class ValidationTracepointTest(BitcoinTestFramework):
nonlocal expected_blocks, blocks_checked
event = ctypes.cast(data, ctypes.POINTER(Block)).contents
self.log.info(f"handle_blockconnected(): {event}")
- block = expected_blocks.pop(0)
- assert_equal(block["hash"], bytes(event.hash[::-1]).hex())
+ block_hash = bytes(event.hash[::-1]).hex()
+ block = expected_blocks[block_hash]
+ assert_equal(block["hash"], block_hash)
assert_equal(block["height"], event.height)
assert_equal(len(block["tx"]), event.transactions)
assert_equal(len([tx["vin"] for tx in block["tx"]]), event.inputs)
assert_equal(0, event.sigops) # no sigops in coinbase tx
# only plausibility checks
assert(event.duration > 0)
-
+ del expected_blocks[block_hash]
blocks_checked += 1
bpf["block_connected"].open_perf_buffer(
@@ -122,7 +123,7 @@ class ValidationTracepointTest(BitcoinTestFramework):
block_hashes = self.generatetoaddress(
self.nodes[0], BLOCKS_EXPECTED, ADDRESS_BCRT1_UNSPENDABLE)
for block_hash in block_hashes:
- expected_blocks.append(self.nodes[0].getblock(block_hash, 2))
+ expected_blocks[block_hash] = self.nodes[0].getblock(block_hash, 2)
bpf.perf_buffer_poll(timeout=200)
bpf.cleanup()
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index 85464b8d0d..02ec18140c 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -11,7 +11,7 @@ import math
from test_framework.test_framework import BitcoinTestFramework
from test_framework.key import ECKey
from test_framework.messages import (
- BIP125_SEQUENCE_NUMBER,
+ MAX_BIP125_RBF_SEQUENCE,
COIN,
COutPoint,
CTxIn,
@@ -65,7 +65,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
assert_equal(node.getmempoolinfo()['size'], self.mempool_size)
self.log.info('Should not accept garbage to testmempoolaccept')
- assert_raises_rpc_error(-3, 'Expected type array, got string', lambda: node.testmempoolaccept(rawtxs='ff00baar'))
+ assert_raises_rpc_error(-3, 'JSON value of type string is not of expected type array', lambda: node.testmempoolaccept(rawtxs='ff00baar'))
assert_raises_rpc_error(-8, 'Array must contain between 1 and 25 transactions.', lambda: node.testmempoolaccept(rawtxs=['ff22']*26))
assert_raises_rpc_error(-8, 'Array must contain between 1 and 25 transactions.', lambda: node.testmempoolaccept(rawtxs=[]))
assert_raises_rpc_error(-22, 'TX decode failed', lambda: node.testmempoolaccept(rawtxs=['ff00baar']))
@@ -87,7 +87,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
self.log.info('A transaction not in the mempool')
fee = Decimal('0.000007')
utxo_to_spend = self.wallet.get_utxo(txid=txid_in_block) # use 0.3 BTC UTXO
- tx = self.wallet.create_self_transfer(utxo_to_spend=utxo_to_spend, sequence=BIP125_SEQUENCE_NUMBER)['tx']
+ tx = self.wallet.create_self_transfer(utxo_to_spend=utxo_to_spend, sequence=MAX_BIP125_RBF_SEQUENCE)['tx']
tx.vout[0].nValue = int((Decimal('0.3') - fee) * COIN)
raw_tx_0 = tx.serialize().hex()
txid_0 = tx.rehash()
@@ -125,7 +125,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
self.log.info('A transaction that replaces a mempool transaction')
tx = tx_from_hex(raw_tx_0)
tx.vout[0].nValue -= int(fee * COIN) # Double the fee
- tx.vin[0].nSequence = BIP125_SEQUENCE_NUMBER + 1 # Now, opt out of RBF
+ tx.vin[0].nSequence = MAX_BIP125_RBF_SEQUENCE + 1 # Now, opt out of RBF
raw_tx_0 = tx.serialize().hex()
txid_0 = tx.rehash()
self.check_mempool_result(
diff --git a/test/functional/mempool_datacarrier.py b/test/functional/mempool_datacarrier.py
new file mode 100755
index 0000000000..13df564a37
--- /dev/null
+++ b/test/functional/mempool_datacarrier.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020-2021 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test datacarrier functionality"""
+from test_framework.messages import (
+ CTxOut,
+ MAX_OP_RETURN_RELAY,
+)
+from test_framework.script import (
+ CScript,
+ OP_RETURN,
+)
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.test_node import TestNode
+from test_framework.util import (
+ assert_raises_rpc_error,
+ random_bytes,
+)
+from test_framework.wallet import MiniWallet
+
+
+class DataCarrierTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 3
+ self.extra_args = [
+ [],
+ ["-datacarrier=0"],
+ ["-datacarrier=1", f"-datacarriersize={MAX_OP_RETURN_RELAY - 1}"]
+ ]
+
+ def test_null_data_transaction(self, node: TestNode, data: bytes, success: bool) -> None:
+ tx = self.wallet.create_self_transfer(fee_rate=0)["tx"]
+ tx.vout.append(CTxOut(nValue=0, scriptPubKey=CScript([OP_RETURN, data])))
+ tx.vout[0].nValue -= tx.get_vsize() # simply pay 1sat/vbyte fee
+
+ tx_hex = tx.serialize().hex()
+
+ if success:
+ self.wallet.sendrawtransaction(from_node=node, tx_hex=tx_hex)
+ assert tx.rehash() in node.getrawmempool(True), f'{tx_hex} not in mempool'
+ else:
+ assert_raises_rpc_error(-26, "scriptpubkey", self.wallet.sendrawtransaction, from_node=node, tx_hex=tx_hex)
+
+ def run_test(self):
+ self.wallet = MiniWallet(self.nodes[0])
+ self.wallet.rescan_utxos()
+
+ # By default, only 80 bytes are used for data (+1 for OP_RETURN, +2 for the pushdata opcodes).
+ default_size_data = random_bytes(MAX_OP_RETURN_RELAY - 3)
+ too_long_data = random_bytes(MAX_OP_RETURN_RELAY - 2)
+ small_data = random_bytes(MAX_OP_RETURN_RELAY - 4)
+
+ self.log.info("Testing null data transaction with default -datacarrier and -datacarriersize values.")
+ self.test_null_data_transaction(node=self.nodes[0], data=default_size_data, success=True)
+
+ self.log.info("Testing a null data transaction larger than allowed by the default -datacarriersize value.")
+ self.test_null_data_transaction(node=self.nodes[0], data=too_long_data, success=False)
+
+ self.log.info("Testing a null data transaction with -datacarrier=false.")
+ self.test_null_data_transaction(node=self.nodes[1], data=default_size_data, success=False)
+
+ self.log.info("Testing a null data transaction with a size larger than accepted by -datacarriersize.")
+ self.test_null_data_transaction(node=self.nodes[2], data=default_size_data, success=False)
+
+ self.log.info("Testing a null data transaction with a size smaller than accepted by -datacarriersize.")
+ self.test_null_data_transaction(node=self.nodes[2], data=small_data, success=True)
+
+
+if __name__ == '__main__':
+ DataCarrierTest().main()
diff --git a/test/functional/mempool_expiry.py b/test/functional/mempool_expiry.py
index f301b29c25..21721177e6 100755
--- a/test/functional/mempool_expiry.py
+++ b/test/functional/mempool_expiry.py
@@ -5,7 +5,7 @@
"""Tests that a mempool transaction expires after a given timeout and that its
children are removed as well.
-Both the default expiry timeout defined by DEFAULT_MEMPOOL_EXPIRY and a user
+Both the default expiry timeout defined by DEFAULT_MEMPOOL_EXPIRY_HOURS and a user
definable expiry timeout via the '-mempoolexpiry=<n>' command line argument
(<n> is the timeout in hours) are tested.
"""
@@ -13,6 +13,7 @@ definable expiry timeout via the '-mempoolexpiry=<n>' command line argument
from datetime import timedelta
from test_framework.blocktools import COINBASE_MATURITY
+from test_framework.messages import DEFAULT_MEMPOOL_EXPIRY_HOURS
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -20,7 +21,6 @@ from test_framework.util import (
)
from test_framework.wallet import MiniWallet
-DEFAULT_MEMPOOL_EXPIRY = 336 # hours
CUSTOM_MEMPOOL_EXPIRY = 10 # hours
@@ -98,8 +98,8 @@ class MempoolExpiryTest(BitcoinTestFramework):
def run_test(self):
self.log.info('Test default mempool expiry timeout of %d hours.' %
- DEFAULT_MEMPOOL_EXPIRY)
- self.test_transaction_expiry(DEFAULT_MEMPOOL_EXPIRY)
+ DEFAULT_MEMPOOL_EXPIRY_HOURS)
+ self.test_transaction_expiry(DEFAULT_MEMPOOL_EXPIRY_HOURS)
self.log.info('Test custom mempool expiry timeout of %d hours.' %
CUSTOM_MEMPOOL_EXPIRY)
diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py
index e92f73304b..7080662b49 100755
--- a/test/functional/mempool_limit.py
+++ b/test/functional/mempool_limit.py
@@ -23,7 +23,7 @@ class MempoolLimitTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [[
- "-acceptnonstdtxn=1",
+ "-datacarriersize=100000",
"-maxmempool=5",
"-spendzeroconfchange=0",
]]
diff --git a/test/functional/mempool_package_limits.py b/test/functional/mempool_package_limits.py
index 89a5c83826..1f12e93982 100755
--- a/test/functional/mempool_package_limits.py
+++ b/test/functional/mempool_package_limits.py
@@ -6,28 +6,16 @@
from decimal import Decimal
-from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE
+from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.messages import (
COIN,
- CTransaction,
- CTxInWitness,
- tx_from_hex,
WITNESS_SCALE_FACTOR,
)
-from test_framework.script import (
- CScript,
- OP_TRUE,
-)
from test_framework.util import (
assert_equal,
)
-from test_framework.wallet import (
- bulk_transaction,
- create_child_with_parents,
- make_chain,
- DEFAULT_FEE,
-)
+from test_framework.wallet import MiniWallet
class MempoolPackageLimitsTest(BitcoinTestFramework):
def set_test_params(self):
@@ -35,19 +23,10 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
self.setup_clean_chain = True
def run_test(self):
- self.log.info("Generate blocks to create UTXOs")
- node = self.nodes[0]
- self.privkeys = [node.get_deterministic_priv_key().key]
- self.address = node.get_deterministic_priv_key().address
- self.coins = []
- # The last 100 coinbase transactions are premature
- for b in self.generatetoaddress(node, 200, self.address)[:100]:
- coinbase = node.getblock(blockhash=b, verbosity=2)["tx"][0]
- self.coins.append({
- "txid": coinbase["txid"],
- "amount": coinbase["vout"][0]["value"],
- "scriptPubKey": coinbase["vout"][0]["scriptPubKey"],
- })
+ self.wallet = MiniWallet(self.nodes[0])
+ # Add enough mature utxos to the wallet so that all txs spend confirmed coins.
+ self.generate(self.wallet, 35)
+ self.generate(self.nodes[0], COINBASE_MATURITY)
self.test_chain_limits()
self.test_desc_count_limits()
@@ -56,30 +35,22 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
self.test_anc_count_limits_2()
self.test_anc_count_limits_bushy()
- # The node will accept our (nonstandard) extra large OP_RETURN outputs
- self.restart_node(0, extra_args=["-acceptnonstdtxn=1"])
+ # The node will accept (nonstandard) extra large OP_RETURN outputs
+ self.restart_node(0, extra_args=["-datacarriersize=100000"])
self.test_anc_size_limits()
self.test_desc_size_limits()
def test_chain_limits_helper(self, mempool_count, package_count):
node = self.nodes[0]
assert_equal(0, node.getmempoolinfo()["size"])
- first_coin = self.coins.pop()
- spk = None
- txid = first_coin["txid"]
chain_hex = []
- chain_txns = []
- value = first_coin["amount"]
-
- for i in range(mempool_count + package_count):
- (tx, txhex, value, spk) = make_chain(node, self.address, self.privkeys, txid, value, 0, spk)
- txid = tx.rehash()
- if i < mempool_count:
- node.sendrawtransaction(txhex)
- assert_equal(node.getmempoolentry(txid)["ancestorcount"], i + 1)
- else:
- chain_hex.append(txhex)
- chain_txns.append(tx)
+
+ chaintip_utxo = self.wallet.send_self_transfer_chain(from_node=node, chain_length=mempool_count)
+ # in-package transactions
+ for _ in range(package_count):
+ tx = self.wallet.create_self_transfer(utxo_to_spend=chaintip_utxo)
+ chaintip_utxo = tx["new_utxo"]
+ chain_hex.append(tx["hex"])
testres_too_long = node.testmempoolaccept(rawtxs=chain_hex)
for txres in testres_too_long:
assert_equal(txres["package-error"], "package-mempool-limits")
@@ -125,49 +96,20 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
assert_equal(0, node.getmempoolinfo()["size"])
self.log.info("Check that in-mempool and in-package descendants are calculated properly in packages")
# Top parent in mempool, M1
- first_coin = self.coins.pop()
- parent_value = (first_coin["amount"] - Decimal("0.0002")) / 2 # Deduct reasonable fee and make 2 outputs
- inputs = [{"txid": first_coin["txid"], "vout": 0}]
- outputs = [{self.address : parent_value}, {ADDRESS_BCRT1_P2WSH_OP_TRUE : parent_value}]
- rawtx = node.createrawtransaction(inputs, outputs)
-
- parent_signed = node.signrawtransactionwithkey(hexstring=rawtx, privkeys=self.privkeys)
- assert parent_signed["complete"]
- parent_tx = tx_from_hex(parent_signed["hex"])
- parent_txid = parent_tx.rehash()
- node.sendrawtransaction(parent_signed["hex"])
+ m1_utxos = self.wallet.send_self_transfer_multi(from_node=node, num_outputs=2)['new_utxos']
package_hex = []
-
- # Chain A
- spk = parent_tx.vout[0].scriptPubKey.hex()
- value = parent_value
- txid = parent_txid
- for i in range(12):
- (tx, txhex, value, spk) = make_chain(node, self.address, self.privkeys, txid, value, 0, spk)
- txid = tx.rehash()
- if i < 11: # M2a... M12a
- node.sendrawtransaction(txhex)
- else: # Pa
- package_hex.append(txhex)
-
- # Chain B
- value = parent_value - Decimal("0.0001")
- rawtx_b = node.createrawtransaction([{"txid": parent_txid, "vout": 1}], {self.address : value})
- tx_child_b = tx_from_hex(rawtx_b) # M2b
- tx_child_b.wit.vtxinwit = [CTxInWitness()]
- tx_child_b.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
- tx_child_b_hex = tx_child_b.serialize().hex()
- node.sendrawtransaction(tx_child_b_hex)
- spk = tx_child_b.vout[0].scriptPubKey.hex()
- txid = tx_child_b.rehash()
- for i in range(12):
- (tx, txhex, value, spk) = make_chain(node, self.address, self.privkeys, txid, value, 0, spk)
- txid = tx.rehash()
- if i < 11: # M3b... M13b
- node.sendrawtransaction(txhex)
- else: # Pb
- package_hex.append(txhex)
+ # Chain A (M2a... M12a)
+ chain_a_tip_utxo = self.wallet.send_self_transfer_chain(from_node=node, chain_length=11, utxo_to_spend=m1_utxos[0])
+ # Pa
+ pa_hex = self.wallet.create_self_transfer(utxo_to_spend=chain_a_tip_utxo)["hex"]
+ package_hex.append(pa_hex)
+
+ # Chain B (M2b... M13b)
+ chain_b_tip_utxo = self.wallet.send_self_transfer_chain(from_node=node, chain_length=12, utxo_to_spend=m1_utxos[1])
+ # Pb
+ pb_hex = self.wallet.create_self_transfer(utxo_to_spend=chain_b_tip_utxo)["hex"]
+ package_hex.append(pb_hex)
assert_equal(24, node.getmempoolinfo()["size"])
assert_equal(2, len(package_hex))
@@ -200,41 +142,18 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
node = self.nodes[0]
package_hex = []
# M1
- first_coin_a = self.coins.pop()
- parent_value = (first_coin_a["amount"] - DEFAULT_FEE) / 2 # Deduct reasonable fee and make 2 outputs
- inputs = [{"txid": first_coin_a["txid"], "vout": 0}]
- outputs = [{self.address : parent_value}, {ADDRESS_BCRT1_P2WSH_OP_TRUE : parent_value}]
- rawtx = node.createrawtransaction(inputs, outputs)
-
- parent_signed = node.signrawtransactionwithkey(hexstring=rawtx, privkeys=self.privkeys)
- assert parent_signed["complete"]
- parent_tx = tx_from_hex(parent_signed["hex"])
- parent_txid = parent_tx.rehash()
- node.sendrawtransaction(parent_signed["hex"])
+ m1_utxos = self.wallet.send_self_transfer_multi(from_node=node, num_outputs=2)['new_utxos']
# Chain M2...M24
- spk = parent_tx.vout[0].scriptPubKey.hex()
- value = parent_value
- txid = parent_txid
- for i in range(23): # M2...M24
- (tx, txhex, value, spk) = make_chain(node, self.address, self.privkeys, txid, value, 0, spk)
- txid = tx.rehash()
- node.sendrawtransaction(txhex)
+ self.wallet.send_self_transfer_chain(from_node=node, chain_length=23, utxo_to_spend=m1_utxos[0])
# P1
- value_p1 = (parent_value - DEFAULT_FEE)
- rawtx_p1 = node.createrawtransaction([{"txid": parent_txid, "vout": 1}], [{self.address : value_p1}])
- tx_child_p1 = tx_from_hex(rawtx_p1)
- tx_child_p1.wit.vtxinwit = [CTxInWitness()]
- tx_child_p1.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
- tx_child_p1_hex = tx_child_p1.serialize().hex()
- txid_child_p1 = tx_child_p1.rehash()
- package_hex.append(tx_child_p1_hex)
- tx_child_p1_spk = tx_child_p1.vout[0].scriptPubKey.hex()
+ p1_tx = self.wallet.create_self_transfer(utxo_to_spend=m1_utxos[1])
+ package_hex.append(p1_tx["hex"])
# P2
- (_, tx_child_p2_hex, _, _) = make_chain(node, self.address, self.privkeys, txid_child_p1, value_p1, 0, tx_child_p1_spk)
- package_hex.append(tx_child_p2_hex)
+ p2_tx = self.wallet.create_self_transfer(utxo_to_spend=p1_tx["new_utxo"])
+ package_hex.append(p2_tx["hex"])
assert_equal(24, node.getmempoolinfo()["size"])
assert_equal(2, len(package_hex))
@@ -266,32 +185,21 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
node = self.nodes[0]
assert_equal(0, node.getmempoolinfo()["size"])
package_hex = []
- parents_tx = []
- values = []
- scripts = []
+ pc_parent_utxos = []
self.log.info("Check that in-mempool and in-package ancestors are calculated properly in packages")
# Two chains of 13 transactions each
for _ in range(2):
- spk = None
- top_coin = self.coins.pop()
- txid = top_coin["txid"]
- value = top_coin["amount"]
- for i in range(13):
- (tx, txhex, value, spk) = make_chain(node, self.address, self.privkeys, txid, value, 0, spk)
- txid = tx.rehash()
- if i < 12:
- node.sendrawtransaction(txhex)
- else: # Save the 13th transaction for the package
- package_hex.append(txhex)
- parents_tx.append(tx)
- scripts.append(spk)
- values.append(value)
+ chain_tip_utxo = self.wallet.send_self_transfer_chain(from_node=node, chain_length=12)
+ # Save the 13th transaction for the package
+ tx = self.wallet.create_self_transfer(utxo_to_spend=chain_tip_utxo)
+ package_hex.append(tx["hex"])
+ pc_parent_utxos.append(tx["new_utxo"])
# Child Pc
- child_hex = create_child_with_parents(node, self.address, self.privkeys, parents_tx, values, scripts)
- package_hex.append(child_hex)
+ pc_hex = self.wallet.create_self_transfer_multi(utxos_to_spend=pc_parent_utxos)["hex"]
+ package_hex.append(pc_hex)
assert_equal(24, node.getmempoolinfo()["size"])
assert_equal(3, len(package_hex))
@@ -321,45 +229,29 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
"""
node = self.nodes[0]
assert_equal(0, node.getmempoolinfo()["size"])
- parents_tx = []
- values = []
- scripts = []
+ pc_parent_utxos = []
self.log.info("Check that in-mempool and in-package ancestors are calculated properly in packages")
# Two chains of 12 transactions each
for _ in range(2):
- spk = None
- top_coin = self.coins.pop()
- txid = top_coin["txid"]
- value = top_coin["amount"]
- for i in range(12):
- (tx, txhex, value, spk) = make_chain(node, self.address, self.privkeys, txid, value, 0, spk)
- txid = tx.rehash()
- value -= Decimal("0.0001")
- node.sendrawtransaction(txhex)
- if i == 11:
- # last 2 transactions will be the parents of Pc
- parents_tx.append(tx)
- values.append(value)
- scripts.append(spk)
+ chaintip_utxo = self.wallet.send_self_transfer_chain(from_node=node, chain_length=12)
+ # last 2 transactions will be the parents of Pc
+ pc_parent_utxos.append(chaintip_utxo)
# Child Pc
- pc_hex = create_child_with_parents(node, self.address, self.privkeys, parents_tx, values, scripts)
- pc_tx = tx_from_hex(pc_hex)
- pc_value = sum(values) - Decimal("0.0002")
- pc_spk = pc_tx.vout[0].scriptPubKey.hex()
+ pc_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=pc_parent_utxos)
# Child Pd
- (_, pd_hex, _, _) = make_chain(node, self.address, self.privkeys, pc_tx.rehash(), pc_value, 0, pc_spk)
+ pd_tx = self.wallet.create_self_transfer(utxo_to_spend=pc_tx["new_utxos"][0])
assert_equal(24, node.getmempoolinfo()["size"])
- testres_too_long = node.testmempoolaccept(rawtxs=[pc_hex, pd_hex])
+ testres_too_long = node.testmempoolaccept(rawtxs=[pc_tx["hex"], pd_tx["hex"]])
for txres in testres_too_long:
assert_equal(txres["package-error"], "package-mempool-limits")
# Clear mempool and check that the package passes now
self.generate(node, 1)
- assert all([res["allowed"] for res in node.testmempoolaccept(rawtxs=[pc_hex, pd_hex])])
+ assert all([res["allowed"] for res in node.testmempoolaccept(rawtxs=[pc_tx["hex"], pd_tx["hex"]])])
def test_anc_count_limits_bushy(self):
"""Create a tree with 20 transactions in the mempool and 6 in the package:
@@ -375,31 +267,18 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
node = self.nodes[0]
assert_equal(0, node.getmempoolinfo()["size"])
package_hex = []
- parent_txns = []
- parent_values = []
- scripts = []
+ pc_parent_utxos = []
for _ in range(5): # Make package transactions P0 ... P4
- gp_tx = []
- gp_values = []
- gp_scripts = []
+ pc_grandparent_utxos = []
for _ in range(4): # Make mempool transactions M(4i+1)...M(4i+4)
- parent_coin = self.coins.pop()
- value = parent_coin["amount"]
- txid = parent_coin["txid"]
- (tx, txhex, value, spk) = make_chain(node, self.address, self.privkeys, txid, value)
- gp_tx.append(tx)
- gp_values.append(value)
- gp_scripts.append(spk)
- node.sendrawtransaction(txhex)
+ pc_grandparent_utxos.append(self.wallet.send_self_transfer(from_node=node)["new_utxo"])
# Package transaction Pi
- pi_hex = create_child_with_parents(node, self.address, self.privkeys, gp_tx, gp_values, gp_scripts)
- package_hex.append(pi_hex)
- pi_tx = tx_from_hex(pi_hex)
- parent_txns.append(pi_tx)
- parent_values.append(Decimal(pi_tx.vout[0].nValue) / COIN)
- scripts.append(pi_tx.vout[0].scriptPubKey.hex())
+ pi_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=pc_grandparent_utxos)
+ package_hex.append(pi_tx["hex"])
+ pc_parent_utxos.append(pi_tx["new_utxos"][0])
# Package transaction PC
- package_hex.append(create_child_with_parents(node, self.address, self.privkeys, parent_txns, parent_values, scripts))
+ pc_hex = self.wallet.create_self_transfer_multi(utxos_to_spend=pc_parent_utxos)["hex"]
+ package_hex.append(pc_hex)
assert_equal(20, node.getmempoolinfo()["size"])
assert_equal(6, len(package_hex))
@@ -424,51 +303,30 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
"""
node = self.nodes[0]
assert_equal(0, node.getmempoolinfo()["size"])
- parents_tx = []
- values = []
- scripts = []
+ parent_utxos = []
target_weight = WITNESS_SCALE_FACTOR * 1000 * 30 # 30KvB
high_fee = Decimal("0.003") # 10 sats/vB
self.log.info("Check that in-mempool and in-package ancestor size limits are calculated properly in packages")
# Mempool transactions A and B
for _ in range(2):
- spk = None
- top_coin = self.coins.pop()
- txid = top_coin["txid"]
- value = top_coin["amount"]
- (tx, _, _, _) = make_chain(node, self.address, self.privkeys, txid, value, 0, spk, high_fee)
- bulked_tx = bulk_transaction(tx, node, target_weight, self.privkeys)
- node.sendrawtransaction(bulked_tx.serialize().hex())
- parents_tx.append(bulked_tx)
- values.append(Decimal(bulked_tx.vout[0].nValue) / COIN)
- scripts.append(bulked_tx.vout[0].scriptPubKey.hex())
+ bulked_tx = self.wallet.create_self_transfer(target_weight=target_weight)
+ self.wallet.sendrawtransaction(from_node=node, tx_hex=bulked_tx["hex"])
+ parent_utxos.append(bulked_tx["new_utxo"])
# Package transaction C
- small_pc_hex = create_child_with_parents(node, self.address, self.privkeys, parents_tx, values, scripts, high_fee)
- pc_tx = bulk_transaction(tx_from_hex(small_pc_hex), node, target_weight, self.privkeys)
- pc_value = Decimal(pc_tx.vout[0].nValue) / COIN
- pc_spk = pc_tx.vout[0].scriptPubKey.hex()
- pc_hex = pc_tx.serialize().hex()
+ pc_tx = self.wallet.create_self_transfer_multi(utxos_to_spend=parent_utxos, fee_per_output=int(high_fee * COIN), target_weight=target_weight)
# Package transaction D
- (small_pd, _, val, spk) = make_chain(node, self.address, self.privkeys, pc_tx.rehash(), pc_value, 0, pc_spk, high_fee)
- prevtxs = [{
- "txid": pc_tx.rehash(),
- "vout": 0,
- "scriptPubKey": spk,
- "amount": val,
- }]
- pd_tx = bulk_transaction(small_pd, node, target_weight, self.privkeys, prevtxs)
- pd_hex = pd_tx.serialize().hex()
+ pd_tx = self.wallet.create_self_transfer(utxo_to_spend=pc_tx["new_utxos"][0], target_weight=target_weight)
assert_equal(2, node.getmempoolinfo()["size"])
- testres_too_heavy = node.testmempoolaccept(rawtxs=[pc_hex, pd_hex])
+ testres_too_heavy = node.testmempoolaccept(rawtxs=[pc_tx["hex"], pd_tx["hex"]])
for txres in testres_too_heavy:
assert_equal(txres["package-error"], "package-mempool-limits")
# Clear mempool and check that the package passes now
self.generate(node, 1)
- assert all([res["allowed"] for res in node.testmempoolaccept(rawtxs=[pc_hex, pd_hex])])
+ assert all([res["allowed"] for res in node.testmempoolaccept(rawtxs=[pc_tx["hex"], pd_tx["hex"]])])
def test_desc_size_limits(self):
"""Create 3 mempool transactions and 2 package transactions (25KvB each):
@@ -486,50 +344,18 @@ class MempoolPackageLimitsTest(BitcoinTestFramework):
high_fee = Decimal("0.0021") # 10 sats/vB
self.log.info("Check that in-mempool and in-package descendant sizes are calculated properly in packages")
# Top parent in mempool, Ma
- first_coin = self.coins.pop()
- parent_value = (first_coin["amount"] - high_fee) / 2 # Deduct fee and make 2 outputs
- inputs = [{"txid": first_coin["txid"], "vout": 0}]
- outputs = [{self.address : parent_value}, {ADDRESS_BCRT1_P2WSH_OP_TRUE: parent_value}]
- rawtx = node.createrawtransaction(inputs, outputs)
- parent_tx = bulk_transaction(tx_from_hex(rawtx), node, target_weight, self.privkeys)
- node.sendrawtransaction(parent_tx.serialize().hex())
+ ma_tx = self.wallet.create_self_transfer_multi(num_outputs=2, fee_per_output=int(high_fee / 2 * COIN), target_weight=target_weight)
+ self.wallet.sendrawtransaction(from_node=node, tx_hex=ma_tx["hex"])
package_hex = []
for j in range(2): # Two legs (left and right)
# Mempool transaction (Mb and Mc)
- mempool_tx = CTransaction()
- spk = parent_tx.vout[j].scriptPubKey.hex()
- value = Decimal(parent_tx.vout[j].nValue) / COIN
- txid = parent_tx.rehash()
- prevtxs = [{
- "txid": txid,
- "vout": j,
- "scriptPubKey": spk,
- "amount": value,
- }]
- if j == 0: # normal key
- (tx_small, _, _, _) = make_chain(node, self.address, self.privkeys, txid, value, j, spk, high_fee)
- mempool_tx = bulk_transaction(tx_small, node, target_weight, self.privkeys, prevtxs)
- else: # OP_TRUE
- inputs = [{"txid": txid, "vout": 1}]
- outputs = {self.address: value - high_fee}
- small_tx = tx_from_hex(node.createrawtransaction(inputs, outputs))
- mempool_tx = bulk_transaction(small_tx, node, target_weight, None, prevtxs)
- node.sendrawtransaction(mempool_tx.serialize().hex())
+ mempool_tx = self.wallet.create_self_transfer(utxo_to_spend=ma_tx["new_utxos"][j], target_weight=target_weight)
+ self.wallet.sendrawtransaction(from_node=node, tx_hex=mempool_tx["hex"])
# Package transaction (Pd and Pe)
- spk = mempool_tx.vout[0].scriptPubKey.hex()
- value = Decimal(mempool_tx.vout[0].nValue) / COIN
- txid = mempool_tx.rehash()
- (tx_small, _, _, _) = make_chain(node, self.address, self.privkeys, txid, value, 0, spk, high_fee)
- prevtxs = [{
- "txid": txid,
- "vout": 0,
- "scriptPubKey": spk,
- "amount": value,
- }]
- package_tx = bulk_transaction(tx_small, node, target_weight, self.privkeys, prevtxs)
- package_hex.append(package_tx.serialize().hex())
+ package_tx = self.wallet.create_self_transfer(utxo_to_spend=mempool_tx["new_utxo"], target_weight=target_weight)
+ package_hex.append(package_tx["hex"])
assert_equal(3, node.getmempoolinfo()["size"])
assert_equal(2, len(package_hex))
diff --git a/test/functional/mempool_package_onemore.py b/test/functional/mempool_package_onemore.py
index 423a5bf2ee..9a981bd5a5 100755
--- a/test/functional/mempool_package_onemore.py
+++ b/test/functional/mempool_package_onemore.py
@@ -7,6 +7,9 @@
size.
"""
+from test_framework.messages import (
+ DEFAULT_ANCESTOR_LIMIT,
+)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -15,10 +18,6 @@ from test_framework.util import (
from test_framework.wallet import MiniWallet
-MAX_ANCESTORS = 25
-MAX_DESCENDANTS = 25
-
-
class MempoolPackagesTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
@@ -34,19 +33,19 @@ class MempoolPackagesTest(BitcoinTestFramework):
self.wallet = MiniWallet(self.nodes[0])
self.wallet.rescan_utxos()
- # MAX_ANCESTORS transactions off a confirmed tx should be fine
+ # DEFAULT_ANCESTOR_LIMIT transactions off a confirmed tx should be fine
chain = []
utxo = self.wallet.get_utxo()
for _ in range(4):
utxo, utxo2 = self.chain_tx([utxo], num_outputs=2)
chain.append(utxo2)
- for _ in range(MAX_ANCESTORS - 4):
+ for _ in range(DEFAULT_ANCESTOR_LIMIT - 4):
utxo, = self.chain_tx([utxo])
chain.append(utxo)
second_chain, = self.chain_tx([self.wallet.get_utxo()])
- # Check mempool has MAX_ANCESTORS + 1 transactions in it
- assert_equal(len(self.nodes[0].getrawmempool()), MAX_ANCESTORS + 1)
+ # Check mempool has DEFAULT_ANCESTOR_LIMIT + 1 transactions in it
+ assert_equal(len(self.nodes[0].getrawmempool()), DEFAULT_ANCESTOR_LIMIT + 1)
# Adding one more transaction on to the chain should fail.
assert_raises_rpc_error(-26, "too-long-mempool-chain, too many unconfirmed ancestors [limit: 25]", self.chain_tx, [utxo])
@@ -67,7 +66,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
self.nodes[0].sendrawtransaction(replacable_tx.serialize().hex())
# Finally, check that we added two transactions
- assert_equal(len(self.nodes[0].getrawmempool()), MAX_ANCESTORS + 3)
+ assert_equal(len(self.nodes[0].getrawmempool()), DEFAULT_ANCESTOR_LIMIT + 3)
if __name__ == '__main__':
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index a2a2caf324..def0b1fce4 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -7,7 +7,11 @@
from decimal import Decimal
from test_framework.blocktools import COINBASE_MATURITY
-from test_framework.messages import COIN
+from test_framework.messages import (
+ COIN,
+ DEFAULT_ANCESTOR_LIMIT,
+ DEFAULT_DESCENDANT_LIMIT,
+)
from test_framework.p2p import P2PTxInvStore
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -16,13 +20,12 @@ from test_framework.util import (
chain_transaction,
)
-# default limits
-MAX_ANCESTORS = 25
-MAX_DESCENDANTS = 25
+
# custom limits for node1
-MAX_ANCESTORS_CUSTOM = 5
-MAX_DESCENDANTS_CUSTOM = 10
-assert MAX_DESCENDANTS_CUSTOM >= MAX_ANCESTORS_CUSTOM
+CUSTOM_ANCESTOR_LIMIT = 5
+CUSTOM_DESCENDANT_LIMIT = 10
+assert CUSTOM_DESCENDANT_LIMIT >= CUSTOM_ANCESTOR_LIMIT
+
class MempoolPackagesTest(BitcoinTestFramework):
def set_test_params(self):
@@ -34,8 +37,8 @@ class MempoolPackagesTest(BitcoinTestFramework):
],
[
"-maxorphantx=1000",
- "-limitancestorcount={}".format(MAX_ANCESTORS_CUSTOM),
- "-limitdescendantcount={}".format(MAX_DESCENDANTS_CUSTOM),
+ "-limitancestorcount={}".format(CUSTOM_ANCESTOR_LIMIT),
+ "-limitdescendantcount={}".format(CUSTOM_DESCENDANT_LIMIT),
],
]
@@ -55,12 +58,12 @@ class MempoolPackagesTest(BitcoinTestFramework):
assert 'ancestorfees' not in utxo[0]
fee = Decimal("0.0001")
- # MAX_ANCESTORS transactions off a confirmed tx should be fine
+ # DEFAULT_ANCESTOR_LIMIT transactions off a confirmed tx should be fine
chain = []
witness_chain = []
ancestor_vsize = 0
ancestor_fees = Decimal(0)
- for i in range(MAX_ANCESTORS):
+ for i in range(DEFAULT_ANCESTOR_LIMIT):
(txid, sent_value) = chain_transaction(self.nodes[0], [txid], [0], value, fee, 1)
value = sent_value
chain.append(txid)
@@ -81,16 +84,16 @@ class MempoolPackagesTest(BitcoinTestFramework):
# Otherwise, getrawmempool may be inconsistent with getmempoolentry if unbroadcast changes in between
peer_inv_store.wait_for_broadcast(witness_chain)
- # Check mempool has MAX_ANCESTORS transactions in it, and descendant and ancestor
+ # Check mempool has DEFAULT_ANCESTOR_LIMIT transactions in it, and descendant and ancestor
# count and fees should look correct
mempool = self.nodes[0].getrawmempool(True)
- assert_equal(len(mempool), MAX_ANCESTORS)
+ assert_equal(len(mempool), DEFAULT_ANCESTOR_LIMIT)
descendant_count = 1
descendant_fees = 0
descendant_vsize = 0
assert_equal(ancestor_vsize, sum([mempool[tx]['vsize'] for tx in mempool]))
- ancestor_count = MAX_ANCESTORS
+ ancestor_count = DEFAULT_ANCESTOR_LIMIT
assert_equal(ancestor_fees, sum([mempool[tx]['fees']['base'] for tx in mempool]))
descendants = []
@@ -213,9 +216,9 @@ class MempoolPackagesTest(BitcoinTestFramework):
# Check that node1's mempool is as expected (-> custom ancestor limit)
mempool0 = self.nodes[0].getrawmempool(False)
mempool1 = self.nodes[1].getrawmempool(False)
- assert_equal(len(mempool1), MAX_ANCESTORS_CUSTOM)
+ assert_equal(len(mempool1), CUSTOM_ANCESTOR_LIMIT)
assert set(mempool1).issubset(set(mempool0))
- for tx in chain[:MAX_ANCESTORS_CUSTOM]:
+ for tx in chain[:CUSTOM_ANCESTOR_LIMIT]:
assert tx in mempool1
# TODO: more detailed check of node1's mempool (fees etc.)
# check transaction unbroadcast info (should be false if in both mempools)
@@ -240,7 +243,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
# Sign and send up to MAX_DESCENDANT transactions chained off the parent tx
chain = [] # save sent txs for the purpose of checking node1's mempool later (see below)
- for _ in range(MAX_DESCENDANTS - 1):
+ for _ in range(DEFAULT_DESCENDANT_LIMIT - 1):
utxo = transaction_package.pop(0)
(txid, sent_value) = chain_transaction(self.nodes[0], [utxo['txid']], [utxo['vout']], utxo['amount'], fee, 10)
chain.append(txid)
@@ -250,7 +253,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
transaction_package.append({'txid': txid, 'vout': j, 'amount': sent_value})
mempool = self.nodes[0].getrawmempool(True)
- assert_equal(mempool[parent_transaction]['descendantcount'], MAX_DESCENDANTS)
+ assert_equal(mempool[parent_transaction]['descendantcount'], DEFAULT_DESCENDANT_LIMIT)
assert_equal(sorted(mempool[parent_transaction]['spentby']), sorted(tx_children))
for child in tx_children:
@@ -265,14 +268,14 @@ class MempoolPackagesTest(BitcoinTestFramework):
# - parent tx for descendant test
# - txs chained off parent tx (-> custom descendant limit)
self.wait_until(lambda: len(self.nodes[1].getrawmempool()) ==
- MAX_ANCESTORS_CUSTOM + 1 + MAX_DESCENDANTS_CUSTOM, timeout=10)
+ CUSTOM_ANCESTOR_LIMIT + 1 + CUSTOM_DESCENDANT_LIMIT, timeout=10)
mempool0 = self.nodes[0].getrawmempool(False)
mempool1 = self.nodes[1].getrawmempool(False)
assert set(mempool1).issubset(set(mempool0))
assert parent_transaction in mempool1
- for tx in chain[:MAX_DESCENDANTS_CUSTOM]:
+ for tx in chain[:CUSTOM_DESCENDANT_LIMIT]:
assert tx in mempool1
- for tx in chain[MAX_DESCENDANTS_CUSTOM:]:
+ for tx in chain[CUSTOM_DESCENDANT_LIMIT:]:
assert tx not in mempool1
# TODO: more detailed check of node1's mempool (fees etc.)
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
index 8c9379b90b..b6fa7fbd91 100755
--- a/test/functional/mempool_persist.py
+++ b/test/functional/mempool_persist.py
@@ -105,6 +105,11 @@ class MempoolPersistTest(BitcoinTestFramework):
assert_equal(len(self.nodes[0].p2ps), 0)
self.mini_wallet.send_self_transfer(from_node=self.nodes[0])
+ # Test persistence of prioritisation for transactions not in the mempool.
+ # Create a tx and prioritise but don't submit until after the restart.
+ tx_prioritised_not_submitted = self.mini_wallet.create_self_transfer()
+ self.nodes[0].prioritisetransaction(txid=tx_prioritised_not_submitted['txid'], fee_delta=9999)
+
self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.")
self.stop_nodes()
# Give this node a head-start, so we can be "extra-sure" that it didn't load anything later
@@ -125,6 +130,9 @@ class MempoolPersistTest(BitcoinTestFramework):
self.log.debug('Verify all fields are loaded correctly')
assert_equal(last_entry, self.nodes[0].getmempoolentry(txid=last_txid))
+ self.nodes[0].sendrawtransaction(tx_prioritised_not_submitted['hex'])
+ entry_prioritised_before_restart = self.nodes[0].getmempoolentry(txid=tx_prioritised_not_submitted['txid'])
+ assert_equal(entry_prioritised_before_restart['fees']['base'] + Decimal('0.00009999'), entry_prioritised_before_restart['fees']['modified'])
# Verify accounting of mempool transactions after restart is correct
if self.is_sqlite_compiled():
@@ -133,6 +141,16 @@ class MempoolPersistTest(BitcoinTestFramework):
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
assert_equal(node2_balance, wallet_watch.getbalance())
+ mempooldat0 = os.path.join(self.nodes[0].datadir, self.chain, 'mempool.dat')
+ mempooldat1 = os.path.join(self.nodes[1].datadir, self.chain, 'mempool.dat')
+
+ self.log.debug("Force -persistmempool=0 node1 to savemempool to disk via RPC")
+ assert not os.path.exists(mempooldat1)
+ result1 = self.nodes[1].savemempool()
+ assert os.path.isfile(mempooldat1)
+ assert_equal(result1['filename'], mempooldat1)
+ os.remove(mempooldat1)
+
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
self.stop_nodes()
self.start_node(0, extra_args=["-persistmempool=0"])
@@ -143,22 +161,20 @@ class MempoolPersistTest(BitcoinTestFramework):
self.stop_nodes()
self.start_node(0)
assert self.nodes[0].getmempoolinfo()["loaded"]
- assert_equal(len(self.nodes[0].getrawmempool()), 6)
+ assert_equal(len(self.nodes[0].getrawmempool()), 7)
- mempooldat0 = os.path.join(self.nodes[0].datadir, self.chain, 'mempool.dat')
- mempooldat1 = os.path.join(self.nodes[1].datadir, self.chain, 'mempool.dat')
self.log.debug("Remove the mempool.dat file. Verify that savemempool to disk via RPC re-creates it")
os.remove(mempooldat0)
result0 = self.nodes[0].savemempool()
assert os.path.isfile(mempooldat0)
assert_equal(result0['filename'], mempooldat0)
- self.log.debug("Stop nodes, make node1 use mempool.dat from node0. Verify it has 6 transactions")
+ self.log.debug("Stop nodes, make node1 use mempool.dat from node0. Verify it has 7 transactions")
os.rename(mempooldat0, mempooldat1)
self.stop_nodes()
self.start_node(1, extra_args=["-persistmempool"])
assert self.nodes[1].getmempoolinfo()["loaded"]
- assert_equal(len(self.nodes[1].getrawmempool()), 6)
+ assert_equal(len(self.nodes[1].getrawmempool()), 7)
self.log.debug("Prevent bitcoind from writing mempool.dat to disk. Verify that `savemempool` fails")
# to test the exception we are creating a tmp folder called mempool.dat.new
diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py
index 8dd6cc9cea..47ff520713 100755
--- a/test/functional/mempool_reorg.py
+++ b/test/functional/mempool_reorg.py
@@ -68,10 +68,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
assert_raises_rpc_error(-26, 'non-final', self.nodes[0].sendrawtransaction, timelock_tx)
self.log.info("Create spend_2_1 and spend_3_1")
- spend_2_utxo = wallet.get_utxo(txid=spend_2['txid'])
- spend_2_1 = wallet.create_self_transfer(utxo_to_spend=spend_2_utxo)
- spend_3_utxo = wallet.get_utxo(txid=spend_3['txid'])
- spend_3_1 = wallet.create_self_transfer(utxo_to_spend=spend_3_utxo)
+ spend_2_1 = wallet.create_self_transfer(utxo_to_spend=spend_2["new_utxo"])
+ spend_3_1 = wallet.create_self_transfer(utxo_to_spend=spend_3["new_utxo"])
self.log.info("Broadcast and mine spend_3_1")
spend_3_1_id = self.nodes[0].sendrawtransaction(spend_3_1['hex'])
diff --git a/test/functional/mempool_updatefromblock.py b/test/functional/mempool_updatefromblock.py
index 51de582ce0..f97c2223a6 100755
--- a/test/functional/mempool_updatefromblock.py
+++ b/test/functional/mempool_updatefromblock.py
@@ -12,6 +12,9 @@ import time
from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
+from test_framework.address import key_to_p2pkh
+from test_framework.wallet_util import bytes_to_wif
+from test_framework.key import ECKey
class MempoolUpdateFromBlockTest(BitcoinTestFramework):
@@ -19,8 +22,13 @@ class MempoolUpdateFromBlockTest(BitcoinTestFramework):
self.num_nodes = 1
self.extra_args = [['-limitdescendantsize=1000', '-limitancestorsize=1000', '-limitancestorcount=100']]
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
+ def get_new_address(self):
+ key = ECKey()
+ key.generate()
+ pubkey = key.get_pubkey().get_bytes()
+ address = key_to_p2pkh(pubkey)
+ self.priv_keys.append(bytes_to_wif(key.get_bytes()))
+ return address
def transaction_graph_test(self, size, n_tx_to_mine=None, start_input_txid='', end_address='', fee=Decimal(0.00100000)):
"""Create an acyclic tournament (a type of directed graph) of transactions and use it for testing.
@@ -38,11 +46,12 @@ class MempoolUpdateFromBlockTest(BitcoinTestFramework):
More details: https://en.wikipedia.org/wiki/Tournament_(graph_theory)
"""
+ self.priv_keys = [self.nodes[0].get_deterministic_priv_key().key]
if not start_input_txid:
start_input_txid = self.nodes[0].getblock(self.nodes[0].getblockhash(1))['tx'][0]
if not end_address:
- end_address = self.nodes[0].getnewaddress()
+ end_address = self.get_new_address()
first_block_hash = ''
tx_id = []
@@ -74,7 +83,7 @@ class MempoolUpdateFromBlockTest(BitcoinTestFramework):
output_value = ((inputs_value - fee) / Decimal(n_outputs)).quantize(Decimal('0.00000001'))
outputs = {}
for _ in range(n_outputs):
- outputs[self.nodes[0].getnewaddress()] = output_value
+ outputs[self.get_new_address()] = output_value
else:
output_value = (inputs_value - fee).quantize(Decimal('0.00000001'))
outputs = {end_address: output_value}
@@ -84,7 +93,7 @@ class MempoolUpdateFromBlockTest(BitcoinTestFramework):
# Create a new transaction.
unsigned_raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
- signed_raw_tx = self.nodes[0].signrawtransactionwithwallet(unsigned_raw_tx)
+ signed_raw_tx = self.nodes[0].signrawtransactionwithkey(unsigned_raw_tx, self.priv_keys)
tx_id.append(self.nodes[0].sendrawtransaction(signed_raw_tx['hex']))
tx_size.append(self.nodes[0].getmempoolentry(tx_id[-1])['vsize'])
diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py
index fb3974c1d5..3b75b2bc2d 100755
--- a/test/functional/mining_prioritisetransaction.py
+++ b/test/functional/mining_prioritisetransaction.py
@@ -26,7 +26,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
self.num_nodes = 1
self.extra_args = [[
"-printpriority=1",
- "-acceptnonstdtxn=1",
+ "-datacarriersize=100000",
]] * self.num_nodes
self.supports_cli = False
@@ -122,11 +122,11 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
# Test `prioritisetransaction` invalid `dummy`
txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
- assert_raises_rpc_error(-1, "JSON value is not a number as expected", self.nodes[0].prioritisetransaction, txid, 'foo', 0)
+ assert_raises_rpc_error(-1, "JSON value of type string is not of expected type number", self.nodes[0].prioritisetransaction, txid, 'foo', 0)
assert_raises_rpc_error(-8, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.", self.nodes[0].prioritisetransaction, txid, 1, 0)
# Test `prioritisetransaction` invalid `fee_delta`
- assert_raises_rpc_error(-1, "JSON value is not an integer as expected", self.nodes[0].prioritisetransaction, txid=txid, fee_delta='foo')
+ assert_raises_rpc_error(-1, "JSON value of type string is not of expected type number", self.nodes[0].prioritisetransaction, txid=txid, fee_delta='foo')
self.test_diamond()
diff --git a/test/functional/mocks/invalid_signer.py b/test/functional/mocks/invalid_signer.py
index e30cc9e20b..14f9fed72e 100755
--- a/test/functional/mocks/invalid_signer.py
+++ b/test/functional/mocks/invalid_signer.py
@@ -18,7 +18,7 @@ def perform_pre_checks():
sys.exit(int(mock_result[0]))
def enumerate(args):
- sys.stdout.write(json.dumps([{"fingerprint": "b3c19bfc", "type": "trezor", "model": "trezor_t"}, {"fingerprint": "00000002"}]))
+ sys.stdout.write(json.dumps([{"fingerprint": "b3c19bfc", "type": "trezor", "model": "trezor_t"}]))
def getdescriptors(args):
xpub_pkh = "xpub6CRhJvXV8x2AKWvqi1ZSMFU6cbxzQiYrv3dxSUXCawjMJ1JzpqVsveH4way1yCmJm29KzH1zrVZmVwes4Qo6oXVE1HFn4fdiKrYJngqFFc6"
diff --git a/test/functional/mocks/multi_signers.py b/test/functional/mocks/multi_signers.py
new file mode 100755
index 0000000000..88f93e23de
--- /dev/null
+++ b/test/functional/mocks/multi_signers.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import argparse
+import json
+import sys
+
+def enumerate(args):
+ sys.stdout.write(json.dumps([{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"},
+ {"fingerprint": "00000002", "type": "trezor", "model": "trezor_one"}]))
+
+parser = argparse.ArgumentParser(prog='./multi_signers.py', description='External multi-signer mock')
+
+subparsers = parser.add_subparsers(description='Commands', dest='command')
+subparsers.required = True
+
+parser_enumerate = subparsers.add_parser('enumerate', help='list available signers')
+parser_enumerate.set_defaults(func=enumerate)
+
+
+if not sys.stdin.isatty():
+ buffer = sys.stdin.read()
+ if buffer and buffer.rstrip() != "":
+ sys.argv.extend(buffer.rstrip().split(" "))
+
+args = parser.parse_args()
+
+args.func(args)
diff --git a/test/functional/mocks/signer.py b/test/functional/mocks/signer.py
index b732b26a53..c5a8f7b1e9 100755
--- a/test/functional/mocks/signer.py
+++ b/test/functional/mocks/signer.py
@@ -18,7 +18,7 @@ def perform_pre_checks():
sys.exit(int(mock_result[0]))
def enumerate(args):
- sys.stdout.write(json.dumps([{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"}, {"fingerprint": "00000002"}]))
+ sys.stdout.write(json.dumps([{"fingerprint": "00000001", "type": "trezor", "model": "trezor_t"}]))
def getdescriptors(args):
xpub = "tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B"
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index 5e50e1ebce..3cbb948e3c 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -615,6 +615,27 @@ class CompactBlocksTest(BitcoinTestFramework):
bad_peer.send_message(msg)
bad_peer.wait_for_disconnect()
+ def test_low_work_compactblocks(self, test_node):
+ # A compactblock with insufficient work won't get its header included
+ node = self.nodes[0]
+ hashPrevBlock = int(node.getblockhash(node.getblockcount() - 150), 16)
+ block = self.build_block_on_tip(node)
+ block.hashPrevBlock = hashPrevBlock
+ block.solve()
+
+ comp_block = HeaderAndShortIDs()
+ comp_block.initialize_from_block(block)
+ with self.nodes[0].assert_debug_log(['[net] Ignoring low-work compact block from peer 0']):
+ test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
+
+ tips = node.getchaintips()
+ found = False
+ for x in tips:
+ if x["hash"] == block.hash:
+ found = True
+ break
+ assert not found
+
def test_compactblocks_not_at_tip(self, test_node):
node = self.nodes[0]
# Test that requesting old compactblocks doesn't work.
@@ -833,6 +854,9 @@ class CompactBlocksTest(BitcoinTestFramework):
self.log.info("Testing compactblock requests/announcements not at chain tip...")
self.test_compactblocks_not_at_tip(self.segwit_node)
+ self.log.info("Testing handling of low-work compact blocks...")
+ self.test_low_work_compactblocks(self.segwit_node)
+
self.log.info("Testing handling of incorrect blocktxn responses...")
self.test_incorrect_blocktxn_response(self.segwit_node)
diff --git a/test/functional/p2p_dos_header_tree.py b/test/functional/p2p_dos_header_tree.py
index fde1e4bfa2..7e26994511 100755
--- a/test/functional/p2p_dos_header_tree.py
+++ b/test/functional/p2p_dos_header_tree.py
@@ -22,6 +22,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.chain = 'testnet3' # Use testnet chain because it has an early checkpoint
self.num_nodes = 2
+ self.extra_args = [["-minimumchainwork=0x0"], ["-minimumchainwork=0x0"]]
def add_options(self, parser):
parser.add_argument(
@@ -62,7 +63,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
self.log.info("Feed all fork headers (succeeds without checkpoint)")
# On node 0 it succeeds because checkpoints are disabled
- self.restart_node(0, extra_args=['-nocheckpoints'])
+ self.restart_node(0, extra_args=['-nocheckpoints', "-minimumchainwork=0x0"])
peer_no_checkpoint = self.nodes[0].add_p2p_connection(P2PInterface())
peer_no_checkpoint.send_and_ping(msg_headers(self.headers_fork))
assert {
diff --git a/test/functional/p2p_headers_sync_with_minchainwork.py b/test/functional/p2p_headers_sync_with_minchainwork.py
new file mode 100755
index 0000000000..991e3348ed
--- /dev/null
+++ b/test/functional/p2p_headers_sync_with_minchainwork.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019-2021 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test that we reject low difficulty headers to prevent our block tree from filling up with useless bloat"""
+
+from test_framework.test_framework import BitcoinTestFramework
+
+from test_framework.p2p import (
+ P2PInterface,
+)
+
+from test_framework.messages import (
+ msg_headers,
+)
+
+from test_framework.blocktools import (
+ NORMAL_GBT_REQUEST_PARAMS,
+ create_block,
+)
+
+from test_framework.util import assert_equal
+
+NODE1_BLOCKS_REQUIRED = 15
+NODE2_BLOCKS_REQUIRED = 2047
+
+
+class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 4
+ # Node0 has no required chainwork; node1 requires 15 blocks on top of the genesis block; node2 requires 2047
+ self.extra_args = [["-minimumchainwork=0x0", "-checkblockindex=0"], ["-minimumchainwork=0x1f", "-checkblockindex=0"], ["-minimumchainwork=0x1000", "-checkblockindex=0"], ["-minimumchainwork=0x1000", "-checkblockindex=0", "-whitelist=noban@127.0.0.1"]]
+
+ def setup_network(self):
+ self.setup_nodes()
+ self.reconnect_all()
+ self.sync_all()
+
+ def disconnect_all(self):
+ self.disconnect_nodes(0, 1)
+ self.disconnect_nodes(0, 2)
+ self.disconnect_nodes(0, 3)
+
+ def reconnect_all(self):
+ self.connect_nodes(0, 1)
+ self.connect_nodes(0, 2)
+ self.connect_nodes(0, 3)
+
+ def test_chains_sync_when_long_enough(self):
+ self.log.info("Generate blocks on the node with no required chainwork, and verify nodes 1 and 2 have no new headers in their headers tree")
+ with self.nodes[1].assert_debug_log(expected_msgs=["[net] Ignoring low-work chain (height=14)"]), self.nodes[2].assert_debug_log(expected_msgs=["[net] Ignoring low-work chain (height=14)"]), self.nodes[3].assert_debug_log(expected_msgs=["Synchronizing blockheaders, height: 14"]):
+ self.generate(self.nodes[0], NODE1_BLOCKS_REQUIRED-1, sync_fun=self.no_op)
+
+ # Node3 should always allow headers due to noban permissions
+ self.log.info("Check that node3 will sync headers (due to noban permissions)")
+
+ def check_node3_chaintips(num_tips, tip_hash, height):
+ node3_chaintips = self.nodes[3].getchaintips()
+ assert(len(node3_chaintips) == num_tips)
+ assert {
+ 'height': height,
+ 'hash': tip_hash,
+ 'branchlen': height,
+ 'status': 'headers-only',
+ } in node3_chaintips
+
+ check_node3_chaintips(2, self.nodes[0].getbestblockhash(), NODE1_BLOCKS_REQUIRED-1)
+
+ for node in self.nodes[1:3]:
+ chaintips = node.getchaintips()
+ assert(len(chaintips) == 1)
+ assert {
+ 'height': 0,
+ 'hash': '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206',
+ 'branchlen': 0,
+ 'status': 'active',
+ } in chaintips
+
+ self.log.info("Generate more blocks to satisfy node1's minchainwork requirement, and verify node2 still has no new headers in headers tree")
+ with self.nodes[2].assert_debug_log(expected_msgs=["[net] Ignoring low-work chain (height=15)"]), self.nodes[3].assert_debug_log(expected_msgs=["Synchronizing blockheaders, height: 15"]):
+ self.generate(self.nodes[0], NODE1_BLOCKS_REQUIRED - self.nodes[0].getblockcount(), sync_fun=self.no_op)
+ self.sync_blocks(self.nodes[0:2]) # node3 will sync headers (noban permissions) but not blocks (due to minchainwork)
+
+ assert {
+ 'height': 0,
+ 'hash': '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206',
+ 'branchlen': 0,
+ 'status': 'active',
+ } in self.nodes[2].getchaintips()
+
+ assert(len(self.nodes[2].getchaintips()) == 1)
+
+ self.log.info("Check that node3 accepted these headers as well")
+ check_node3_chaintips(2, self.nodes[0].getbestblockhash(), NODE1_BLOCKS_REQUIRED)
+
+ self.log.info("Generate long chain for node0/node1/node3")
+ self.generate(self.nodes[0], NODE2_BLOCKS_REQUIRED-self.nodes[0].getblockcount(), sync_fun=self.no_op)
+
+ self.log.info("Verify that node2 and node3 will sync the chain when it gets long enough")
+ self.sync_blocks()
+
+ def test_peerinfo_includes_headers_presync_height(self):
+ self.log.info("Test that getpeerinfo() includes headers presync height")
+
+ # Disconnect network, so that we can find our own peer connection more
+ # easily
+ self.disconnect_all()
+
+ p2p = self.nodes[0].add_p2p_connection(P2PInterface())
+ node = self.nodes[0]
+
+ # Ensure we have a long chain already
+ current_height = self.nodes[0].getblockcount()
+ if (current_height < 3000):
+ self.generate(node, 3000-current_height, sync_fun=self.no_op)
+
+ # Send a group of 2000 headers, forking from genesis.
+ new_blocks = []
+ hashPrevBlock = int(node.getblockhash(0), 16)
+ for i in range(2000):
+ block = create_block(hashprev = hashPrevBlock, tmpl=node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS))
+ block.solve()
+ new_blocks.append(block)
+ hashPrevBlock = block.sha256
+
+ headers_message = msg_headers(headers=new_blocks)
+ p2p.send_and_ping(headers_message)
+
+ # getpeerinfo should show a sync in progress
+ assert_equal(node.getpeerinfo()[0]['presynced_headers'], 2000)
+
+ def test_large_reorgs_can_succeed(self):
+ self.log.info("Test that a 2000+ block reorg, starting from a point that is more than 2000 blocks before a locator entry, can succeed")
+
+ self.sync_all() # Ensure all nodes are synced.
+ self.disconnect_all()
+
+ # locator(block at height T) will have heights:
+ # [T, T-1, ..., T-10, T-12, T-16, T-24, T-40, T-72, T-136, T-264,
+ # T-520, T-1032, T-2056, T-4104, ...]
+ # So mine a number of blocks > 4104 to ensure that the first window of
+ # received headers during a sync are fully between locator entries.
+ BLOCKS_TO_MINE = 4110
+
+ self.generate(self.nodes[0], BLOCKS_TO_MINE, sync_fun=self.no_op)
+ self.generate(self.nodes[1], BLOCKS_TO_MINE+2, sync_fun=self.no_op)
+
+ self.reconnect_all()
+
+ self.sync_blocks(timeout=300) # Ensure tips eventually agree
+
+
+ def run_test(self):
+ self.test_chains_sync_when_long_enough()
+
+ self.test_large_reorgs_can_succeed()
+
+ self.test_peerinfo_includes_headers_presync_height()
+
+
+
+if __name__ == '__main__':
+ RejectLowDifficultyHeadersTest().main()
diff --git a/test/functional/p2p_i2p_sessions.py b/test/functional/p2p_i2p_sessions.py
new file mode 100755
index 0000000000..4e52522b81
--- /dev/null
+++ b/test/functional/p2p_i2p_sessions.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022-2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""
+Test whether persistent or transient I2P sessions are being used, based on `-i2pacceptincoming`.
+"""
+
+from test_framework.test_framework import BitcoinTestFramework
+
+
+class I2PSessions(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 2
+ # The test assumes that an I2P SAM proxy is not listening here.
+ self.extra_args = [
+ ["-i2psam=127.0.0.1:60000", "-i2pacceptincoming=1"],
+ ["-i2psam=127.0.0.1:60000", "-i2pacceptincoming=0"],
+ ]
+
+ def run_test(self):
+ addr = "zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtya4snkoka.b32.i2p"
+
+ self.log.info("Ensure we create a persistent session when -i2pacceptincoming=1")
+ node0 = self.nodes[0]
+ with node0.assert_debug_log(expected_msgs=[f"Creating persistent SAM session"]):
+ node0.addnode(node=addr, command="onetry")
+
+ self.log.info("Ensure we create a transient session when -i2pacceptincoming=0")
+ node1 = self.nodes[1]
+ with node1.assert_debug_log(expected_msgs=[f"Creating transient SAM session"]):
+ node1.addnode(node=addr, command="onetry")
+
+
+if __name__ == '__main__':
+ I2PSessions().main()
diff --git a/test/functional/p2p_initial_headers_sync.py b/test/functional/p2p_initial_headers_sync.py
new file mode 100755
index 0000000000..e67c384da7
--- /dev/null
+++ b/test/functional/p2p_initial_headers_sync.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test initial headers download
+
+Test that we only try to initially sync headers from one peer (until our chain
+is close to caught up), and that each block announcement results in only one
+additional peer receiving a getheaders message.
+"""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.messages import (
+ CInv,
+ MSG_BLOCK,
+ msg_headers,
+ msg_inv,
+)
+from test_framework.p2p import (
+ p2p_lock,
+ P2PInterface,
+)
+from test_framework.util import (
+ assert_equal,
+)
+import random
+
+class HeadersSyncTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ def announce_random_block(self, peers):
+ new_block_announcement = msg_inv(inv=[CInv(MSG_BLOCK, random.randrange(1<<256))])
+ for p in peers:
+ p.send_and_ping(new_block_announcement)
+
+ def run_test(self):
+ self.log.info("Adding a peer to node0")
+ peer1 = self.nodes[0].add_p2p_connection(P2PInterface())
+
+ # Wait for peer1 to receive a getheaders
+ peer1.wait_for_getheaders()
+ # An empty reply will clear the outstanding getheaders request,
+ # allowing additional getheaders requests to be sent to this peer in
+ # the future.
+ peer1.send_message(msg_headers())
+
+ self.log.info("Connecting two more peers to node0")
+ # Connect 2 more peers; they should not receive a getheaders yet
+ peer2 = self.nodes[0].add_p2p_connection(P2PInterface())
+ peer3 = self.nodes[0].add_p2p_connection(P2PInterface())
+
+ all_peers = [peer1, peer2, peer3]
+
+ self.log.info("Verify that peer2 and peer3 don't receive a getheaders after connecting")
+ for p in all_peers:
+ p.sync_with_ping()
+ with p2p_lock:
+ assert "getheaders" not in peer2.last_message
+ assert "getheaders" not in peer3.last_message
+
+ with p2p_lock:
+ peer1.last_message.pop("getheaders", None)
+
+ self.log.info("Have all peers announce a new block")
+ self.announce_random_block(all_peers)
+
+ self.log.info("Check that peer1 receives a getheaders in response")
+ peer1.wait_for_getheaders()
+ peer1.send_message(msg_headers()) # Send empty response, see above
+ with p2p_lock:
+ peer1.last_message.pop("getheaders", None)
+
+ self.log.info("Check that exactly 1 of {peer2, peer3} received a getheaders in response")
+ count = 0
+ peer_receiving_getheaders = None
+ for p in [peer2, peer3]:
+ with p2p_lock:
+ if "getheaders" in p.last_message:
+ count += 1
+ peer_receiving_getheaders = p
+ p.last_message.pop("getheaders", None)
+ p.send_message(msg_headers()) # Send empty response, see above
+
+ assert_equal(count, 1)
+
+ self.log.info("Announce another new block, from all peers")
+ self.announce_random_block(all_peers)
+
+ self.log.info("Check that peer1 receives a getheaders in response")
+ peer1.wait_for_getheaders()
+
+ self.log.info("Check that the remaining peer received a getheaders as well")
+ expected_peer = peer2
+ if peer2 == peer_receiving_getheaders:
+ expected_peer = peer3
+
+ expected_peer.wait_for_getheaders()
+
+ self.log.info("Success!")
+
+if __name__ == '__main__':
+ HeadersSyncTest().main()
+
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index 139f4d64e7..28efd5a81e 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -60,7 +60,6 @@ class InvalidTxRequestTest(BitcoinTestFramework):
block.solve()
# Save the coinbase for later
block1 = block
- tip = block.sha256
node.p2ps[0].send_blocks_and_test([block], node, success=True)
self.log.info("Mature the block.")
@@ -93,24 +92,24 @@ class InvalidTxRequestTest(BitcoinTestFramework):
SCRIPT_PUB_KEY_OP_TRUE = b'\x51\x75' * 15 + b'\x51'
tx_withhold = CTransaction()
tx_withhold.vin.append(CTxIn(outpoint=COutPoint(block1.vtx[0].sha256, 0)))
- tx_withhold.vout.append(CTxOut(nValue=50 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_withhold.vout = [CTxOut(nValue=25 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 2
tx_withhold.calc_sha256()
# Our first orphan tx with some outputs to create further orphan txs
tx_orphan_1 = CTransaction()
tx_orphan_1.vin.append(CTxIn(outpoint=COutPoint(tx_withhold.sha256, 0)))
- tx_orphan_1.vout = [CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 3
+ tx_orphan_1.vout = [CTxOut(nValue=8 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 3
tx_orphan_1.calc_sha256()
# A valid transaction with low fee
tx_orphan_2_no_fee = CTransaction()
tx_orphan_2_no_fee.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 0)))
- tx_orphan_2_no_fee.vout.append(CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_orphan_2_no_fee.vout.append(CTxOut(nValue=8 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
# A valid transaction with sufficient fee
tx_orphan_2_valid = CTransaction()
tx_orphan_2_valid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 1)))
- tx_orphan_2_valid.vout.append(CTxOut(nValue=10 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_orphan_2_valid.vout.append(CTxOut(nValue=8 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
tx_orphan_2_valid.calc_sha256()
# An invalid transaction with negative fee
@@ -157,6 +156,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
with node.assert_debug_log(['orphanage overflow, removed 1 tx']):
node.p2ps[0].send_txs_and_test(orphan_tx_pool, node, success=False)
+ self.log.info('Test orphan with rejected parents')
rejected_parent = CTransaction()
rejected_parent.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_2_invalid.sha256, 0)))
rejected_parent.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
@@ -164,6 +164,64 @@ class InvalidTxRequestTest(BitcoinTestFramework):
with node.assert_debug_log(['not keeping orphan with rejected parents {}'.format(rejected_parent.hash)]):
node.p2ps[0].send_txs_and_test([rejected_parent], node, success=False)
+ self.log.info('Test that a peer disconnection causes erase its transactions from the orphan pool')
+ with node.assert_debug_log(['Erased 100 orphan tx from peer=25']):
+ self.reconnect_p2p(num_connections=1)
+
+ self.log.info('Test that a transaction in the orphan pool is included in a new tip block causes erase this transaction from the orphan pool')
+ tx_withhold_until_block_A = CTransaction()
+ tx_withhold_until_block_A.vin.append(CTxIn(outpoint=COutPoint(tx_withhold.sha256, 1)))
+ tx_withhold_until_block_A.vout = [CTxOut(nValue=12 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 2
+ tx_withhold_until_block_A.calc_sha256()
+
+ tx_orphan_include_by_block_A = CTransaction()
+ tx_orphan_include_by_block_A.vin.append(CTxIn(outpoint=COutPoint(tx_withhold_until_block_A.sha256, 0)))
+ tx_orphan_include_by_block_A.vout.append(CTxOut(nValue=12 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_orphan_include_by_block_A.calc_sha256()
+
+ self.log.info('Send the orphan ... ')
+ node.p2ps[0].send_txs_and_test([tx_orphan_include_by_block_A], node, success=False)
+
+ tip = int(node.getbestblockhash(), 16)
+ height = node.getblockcount() + 1
+ block_A = create_block(tip, create_coinbase(height))
+ block_A.vtx.extend([tx_withhold, tx_withhold_until_block_A, tx_orphan_include_by_block_A])
+ block_A.hashMerkleRoot = block_A.calc_merkle_root()
+ block_A.solve()
+
+ self.log.info('Send the block that includes the previous orphan ... ')
+ with node.assert_debug_log(["Erased 1 orphan tx included or conflicted by block"]):
+ node.p2ps[0].send_blocks_and_test([block_A], node, success=True)
+
+ self.log.info('Test that a transaction in the orphan pool conflicts with a new tip block causes erase this transaction from the orphan pool')
+ tx_withhold_until_block_B = CTransaction()
+ tx_withhold_until_block_B.vin.append(CTxIn(outpoint=COutPoint(tx_withhold_until_block_A.sha256, 1)))
+ tx_withhold_until_block_B.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_withhold_until_block_B.calc_sha256()
+
+ tx_orphan_include_by_block_B = CTransaction()
+ tx_orphan_include_by_block_B.vin.append(CTxIn(outpoint=COutPoint(tx_withhold_until_block_B.sha256, 0)))
+ tx_orphan_include_by_block_B.vout.append(CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_orphan_include_by_block_B.calc_sha256()
+
+ tx_orphan_conflict_by_block_B = CTransaction()
+ tx_orphan_conflict_by_block_B.vin.append(CTxIn(outpoint=COutPoint(tx_withhold_until_block_B.sha256, 0)))
+ tx_orphan_conflict_by_block_B.vout.append(CTxOut(nValue=9 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_orphan_conflict_by_block_B.calc_sha256()
+ self.log.info('Send the orphan ... ')
+ node.p2ps[0].send_txs_and_test([tx_orphan_conflict_by_block_B], node, success=False)
+
+ tip = int(node.getbestblockhash(), 16)
+ height = node.getblockcount() + 1
+ block_B = create_block(tip, create_coinbase(height))
+ block_B.vtx.extend([tx_withhold_until_block_B, tx_orphan_include_by_block_B])
+ block_B.hashMerkleRoot = block_B.calc_merkle_root()
+ block_B.solve()
+
+ self.log.info('Send the block that includes a transaction which conflicts with the previous orphan ... ')
+ with node.assert_debug_log(["Erased 1 orphan tx included or conflicted by block"]):
+ node.p2ps[0].send_blocks_and_test([block_B], node, success=True)
+
if __name__ == '__main__':
InvalidTxRequestTest().main()
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index af8e45d578..936c22197c 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -138,6 +138,9 @@ class P2PLeakTest(BitcoinTestFramework):
# Give the node enough time to possibly leak out a message
time.sleep(PEER_TIMEOUT + 2)
+ self.log.info("Connect peer to ensure the net thread runs the disconnect logic at least once")
+ self.nodes[0].add_p2p_connection(P2PInterface())
+
# Make sure only expected messages came in
assert not no_version_idle_peer.unexpected_msg
assert not no_version_idle_peer.got_wtxidrelay
@@ -169,7 +172,7 @@ class P2PLeakTest(BitcoinTestFramework):
self.log.info('Check that old peers are disconnected')
p2p_old_peer = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)
- with self.nodes[0].assert_debug_log(['peer=4 using obsolete version 31799; disconnecting']):
+ with self.nodes[0].assert_debug_log(["using obsolete version 31799; disconnecting"]):
p2p_old_peer.send_message(self.create_old_version(31799))
p2p_old_peer.wait_for_disconnect()
diff --git a/test/functional/p2p_permissions.py b/test/functional/p2p_permissions.py
index 1dc3a5b9a0..453a0920cc 100755
--- a/test/functional/p2p_permissions.py
+++ b/test/functional/p2p_permissions.py
@@ -91,6 +91,7 @@ class P2PPermissionsTests(BitcoinTestFramework):
self.nodes[1].assert_start_raises_init_error(["-whitelist=oopsie@127.0.0.1"], "Invalid P2P permission", match=ErrorMatch.PARTIAL_REGEX)
self.nodes[1].assert_start_raises_init_error(["-whitelist=noban@127.0.0.1:230"], "Invalid netmask specified in", match=ErrorMatch.PARTIAL_REGEX)
self.nodes[1].assert_start_raises_init_error(["-whitebind=noban@127.0.0.1/10"], "Cannot resolve -whitebind address", match=ErrorMatch.PARTIAL_REGEX)
+ self.nodes[1].assert_start_raises_init_error(["-whitebind=noban@127.0.0.1", "-bind=127.0.0.1", "-listen=0"], "Cannot set -bind or -whitebind together with -listen=0", match=ErrorMatch.PARTIAL_REGEX)
def check_tx_relay(self):
block_op_true = self.nodes[0].getblock(self.generatetoaddress(self.nodes[0], 100, ADDRESS_BCRT1_P2WSH_OP_TRUE)[0])
@@ -110,7 +111,8 @@ class P2PPermissionsTests(BitcoinTestFramework):
'vout': 0,
}], outputs=[{
ADDRESS_BCRT1_P2WSH_OP_TRUE: 5,
- }]),
+ }],
+ replaceable=False),
)
tx.wit.vtxinwit = [CTxInWitness()]
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 952f1e5cc5..311b0b67db 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -16,7 +16,7 @@ from test_framework.blocktools import (
)
from test_framework.key import ECKey
from test_framework.messages import (
- BIP125_SEQUENCE_NUMBER,
+ MAX_BIP125_RBF_SEQUENCE,
CBlockHeader,
CInv,
COutPoint,
@@ -245,7 +245,7 @@ class SegWitTest(BitcoinTestFramework):
self.test_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
# self.old_node sets only NODE_NETWORK
self.old_node = self.nodes[0].add_p2p_connection(TestP2PConn(), services=NODE_NETWORK)
- # self.std_node is for testing node1 (fRequireStandard=true)
+ # self.std_node is for testing node1 (requires standard txs)
self.std_node = self.nodes[1].add_p2p_connection(TestP2PConn(), services=P2P_SERVICES)
# self.std_wtx_node is for testing node1 with wtxid relay
self.std_wtx_node = self.nodes[1].add_p2p_connection(TestP2PConn(wtxidrelay=True), services=P2P_SERVICES)
@@ -371,6 +371,10 @@ class SegWitTest(BitcoinTestFramework):
block1 = self.build_next_block()
block1.solve()
+ # Send an empty headers message, to clear out any prior getheaders
+ # messages that our peer may be waiting for us on.
+ self.test_node.send_message(msg_headers())
+
self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False)
assert self.test_node.last_message["getdata"].inv[0].type == blocktype
test_witness_block(self.nodes[0], self.test_node, block1, True)
@@ -585,7 +589,7 @@ class SegWitTest(BitcoinTestFramework):
tx.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_script]))]
tx.vout = [CTxOut(p2sh_tx.vout[0].nValue - 10000, script_pubkey)]
tx.vout.append(CTxOut(8000, script_pubkey)) # Might burn this later
- tx.vin[0].nSequence = BIP125_SEQUENCE_NUMBER # Just to have the option to bump this tx from the mempool
+ tx.vin[0].nSequence = MAX_BIP125_RBF_SEQUENCE # Just to have the option to bump this tx from the mempool
tx.rehash()
# This is always accepted, since the mempool policy is to consider segwit as always active
@@ -1378,7 +1382,7 @@ class SegWitTest(BitcoinTestFramework):
tx3.vout.append(CTxOut(total_value - 1000, script_pubkey))
tx3.rehash()
- # First we test this transaction against fRequireStandard=true node
+ # First we test this transaction against std_node
# making sure the txid is added to the reject filter
self.std_node.announce_tx_and_wait_for_getdata(tx3)
test_transaction_acceptance(self.nodes[1], self.std_node, tx3, with_witness=True, accepted=False, reason="bad-txns-nonstandard-inputs")
@@ -1386,7 +1390,7 @@ class SegWitTest(BitcoinTestFramework):
self.std_node.announce_tx_and_wait_for_getdata(tx3, success=False)
# Spending a higher version witness output is not allowed by policy,
- # even with fRequireStandard=false.
+ # even with the node that accepts non-standard txs.
test_transaction_acceptance(self.nodes[0], self.test_node, tx3, with_witness=True, accepted=False, reason="reserved for soft-fork upgrades")
# Building a block with the transaction must be valid, however.
diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py
index f0abbc7d8b..15a879ae3c 100755
--- a/test/functional/p2p_timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -94,6 +94,11 @@ class TimeoutsTest(BitcoinTestFramework):
no_version_node.wait_for_disconnect(timeout=1)
no_send_node.wait_for_disconnect(timeout=1)
+ self.stop_nodes(0)
+ self.nodes[0].assert_start_raises_init_error(
+ expected_msg='Error: peertimeout must be a positive integer.',
+ extra_args=['-peertimeout=0'],
+ )
if __name__ == '__main__':
TimeoutsTest().main()
diff --git a/test/functional/p2p_tx_privacy.py b/test/functional/p2p_tx_privacy.py
new file mode 100755
index 0000000000..b885ccdf5d
--- /dev/null
+++ b/test/functional/p2p_tx_privacy.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""
+Test that transaction announcements are only queued for peers that have
+successfully completed the version handshake.
+
+Topology:
+
+ tx_originator ----> node[0] <---- spy
+
+We test that a transaction sent by tx_originator is only relayed to spy
+if it was received after spy's version handshake completed.
+
+1. Fully connect tx_originator
+2. Connect spy (no version handshake)
+3. tx_originator sends tx1
+4. spy completes the version handshake
+5. tx_originator sends tx2
+6. We check that only tx2 is announced on the spy interface
+"""
+from test_framework.messages import (
+ msg_wtxidrelay,
+ msg_verack,
+ msg_tx,
+ CInv,
+ MSG_WTX,
+)
+from test_framework.p2p import (
+ P2PInterface,
+)
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.wallet import MiniWallet
+
+class P2PTxSpy(P2PInterface):
+ def __init__(self):
+ super().__init__()
+ self.all_invs = []
+
+ def on_version(self, message):
+ self.send_message(msg_wtxidrelay())
+
+ def on_inv(self, message):
+ self.all_invs += message.inv
+
+ def wait_for_inv_match(self, expected_inv):
+ self.wait_until(lambda: len(self.all_invs) == 1 and self.all_invs[0] == expected_inv)
+
+class TxPrivacyTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+
+ def run_test(self):
+ self.wallet = MiniWallet(self.nodes[0])
+ self.wallet.rescan_utxos()
+
+ tx_originator = self.nodes[0].add_p2p_connection(P2PInterface())
+ spy = self.nodes[0].add_p2p_connection(P2PTxSpy(), wait_for_verack=False)
+ spy.wait_for_verack()
+
+ # tx_originator sends tx1
+ tx1 = self.wallet.create_self_transfer()["tx"]
+ tx_originator.send_and_ping(msg_tx(tx1))
+
+ # Spy sends the verack
+ spy.send_and_ping(msg_verack())
+
+ # tx_originator sends tx2
+ tx2 = self.wallet.create_self_transfer()["tx"]
+ tx_originator.send_and_ping(msg_tx(tx2))
+
+ # Spy should only get an inv for the second transaction as the first
+ # one was received pre-verack with the spy
+ spy.wait_for_inv_match(CInv(MSG_WTX, tx2.calc_sha256(True)))
+
+if __name__ == '__main__':
+ TxPrivacyTest().main()
diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py
index 76d9b045ce..5030e7af26 100755
--- a/test/functional/p2p_unrequested_blocks.py
+++ b/test/functional/p2p_unrequested_blocks.py
@@ -72,6 +72,13 @@ class AcceptBlockTest(BitcoinTestFramework):
def setup_network(self):
self.setup_nodes()
+ def check_hash_in_chaintips(self, node, blockhash):
+ tips = node.getchaintips()
+ for x in tips:
+ if x["hash"] == blockhash:
+ return True
+ return False
+
def run_test(self):
test_node = self.nodes[0].add_p2p_connection(P2PInterface())
min_work_node = self.nodes[1].add_p2p_connection(P2PInterface())
@@ -89,10 +96,15 @@ class AcceptBlockTest(BitcoinTestFramework):
blocks_h2[i].solve()
block_time += 1
test_node.send_and_ping(msg_block(blocks_h2[0]))
- min_work_node.send_and_ping(msg_block(blocks_h2[1]))
+
+ with self.nodes[1].assert_debug_log(expected_msgs=[f"AcceptBlockHeader: not adding new block header {blocks_h2[1].hash}, missing anti-dos proof-of-work validation"]):
+ min_work_node.send_and_ping(msg_block(blocks_h2[1]))
assert_equal(self.nodes[0].getblockcount(), 2)
assert_equal(self.nodes[1].getblockcount(), 1)
+
+ # Ensure that the header of the second block was also not accepted by node1
+ assert_equal(self.check_hash_in_chaintips(self.nodes[1], blocks_h2[1].hash), False)
self.log.info("First height 2 block accepted by node0; correctly rejected by node1")
# 3. Send another block that builds on genesis.
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index 193bd3f1cd..d8147b3355 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -38,6 +38,7 @@ from test_framework.messages import (
msg_block,
)
from test_framework.p2p import P2PInterface
+from test_framework.script import hash256
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -261,12 +262,12 @@ class BlockchainTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, 'getchaintxstats', self.nodes[0].getchaintxstats, 0, '', 0)
# Test `getchaintxstats` invalid `nblocks`
- assert_raises_rpc_error(-1, "JSON value is not an integer as expected", self.nodes[0].getchaintxstats, '')
+ assert_raises_rpc_error(-1, "JSON value of type string is not of expected type number", self.nodes[0].getchaintxstats, '')
assert_raises_rpc_error(-8, "Invalid block count: should be between 0 and the block's height - 1", self.nodes[0].getchaintxstats, -1)
assert_raises_rpc_error(-8, "Invalid block count: should be between 0 and the block's height - 1", self.nodes[0].getchaintxstats, self.nodes[0].getblockcount())
# Test `getchaintxstats` invalid `blockhash`
- assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getchaintxstats, blockhash=0)
+ assert_raises_rpc_error(-1, "JSON value of type number is not of expected type string", self.nodes[0].getchaintxstats, blockhash=0)
assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 1, for '0')", self.nodes[0].getchaintxstats, blockhash='0')
assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getchaintxstats, blockhash='ZZZ0000000000000000000000000000000000000000000000000000000000000')
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getchaintxstats, blockhash='0000000000000000000000000000000000000000000000000000000000000000')
@@ -452,8 +453,9 @@ class BlockchainTest(BitcoinTestFramework):
# (Previously this was broken based on setting
# `rpc/blockchain.cpp:latestblock` incorrectly.)
#
- b20hash = node.getblockhash(20)
- b20 = node.getblock(b20hash)
+ fork_height = current_height - 100 # choose something vaguely near our tip
+ fork_hash = node.getblockhash(fork_height)
+ fork_block = node.getblock(fork_hash)
def solve_and_send_block(prevhash, height, time):
b = create_block(prevhash, create_coinbase(height), time)
@@ -461,10 +463,10 @@ class BlockchainTest(BitcoinTestFramework):
peer.send_and_ping(msg_block(b))
return b
- b21f = solve_and_send_block(int(b20hash, 16), 21, b20['time'] + 1)
- b22f = solve_and_send_block(b21f.sha256, 22, b21f.nTime + 1)
+ b1 = solve_and_send_block(int(fork_hash, 16), fork_height+1, fork_block['time'] + 1)
+ b2 = solve_and_send_block(b1.sha256, fork_height+2, b1.nTime + 1)
- node.invalidateblock(b22f.hash)
+ node.invalidateblock(b2.hash)
def assert_waitforheight(height, timeout=2):
assert_equal(
@@ -484,6 +486,10 @@ class BlockchainTest(BitcoinTestFramework):
self.wallet.send_self_transfer(fee_rate=fee_per_kb, from_node=node)
blockhash = self.generate(node, 1)[0]
+ def assert_hexblock_hashes(verbosity):
+ block = node.getblock(blockhash, verbosity)
+ assert_equal(blockhash, hash256(bytes.fromhex(block[:160]))[::-1].hex())
+
def assert_fee_not_in_block(verbosity):
block = node.getblock(blockhash, verbosity)
assert 'fee' not in block['tx'][1]
@@ -518,8 +524,13 @@ class BlockchainTest(BitcoinTestFramework):
for vin in tx["vin"]:
assert "prevout" not in vin
+ self.log.info("Test that getblock with verbosity 0 hashes to expected value")
+ assert_hexblock_hashes(0)
+ assert_hexblock_hashes(False)
+
self.log.info("Test that getblock with verbosity 1 doesn't include fee")
assert_fee_not_in_block(1)
+ assert_fee_not_in_block(True)
self.log.info('Test that getblock with verbosity 2 and 3 includes expected fee')
assert_fee_in_block(2)
@@ -536,7 +547,7 @@ class BlockchainTest(BitcoinTestFramework):
datadir = get_datadir_path(self.options.tmpdir, 0)
self.log.info("Test getblock with invalid verbosity type returns proper error message")
- assert_raises_rpc_error(-1, "JSON value is not an integer as expected", node.getblock, blockhash, "2")
+ assert_raises_rpc_error(-1, "JSON value of type string is not of expected type number", node.getblock, blockhash, "2")
def move_block_file(old, new):
old_path = os.path.join(datadir, self.chain, 'blocks', old)
diff --git a/test/functional/rpc_deriveaddresses.py b/test/functional/rpc_deriveaddresses.py
index 42d7d59d56..a69326736d 100755
--- a/test/functional/rpc_deriveaddresses.py
+++ b/test/functional/rpc_deriveaddresses.py
@@ -44,6 +44,13 @@ class DeriveaddressesTest(BitcoinTestFramework):
combo_descriptor = descsum_create("combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)")
assert_equal(self.nodes[0].deriveaddresses(combo_descriptor), ["mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", "mtfUoUax9L4tzXARpw1oTGxWyoogp52KhJ", address, "2NDvEwGfpEqJWfybzpKPHF2XH3jwoQV3D7x"])
+ # Before #26275, bitcoind would crash when deriveaddresses was
+ # called with derivation index 2147483647, which is the maximum
+ # positive value of a signed int32, and - currently - the
+ # maximum value that the deriveaddresses bitcoin RPC call
+ # accepts as derivation index.
+ assert_equal(self.nodes[0].deriveaddresses(descsum_create("wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)"), [2147483647, 2147483647]), ["bcrt1qtzs23vgzpreks5gtygwxf8tv5rldxvvsyfpdkg"])
+
hardened_without_privkey_descriptor = descsum_create("wpkh(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1'/1/0)")
assert_raises_rpc_error(-5, "Cannot derive script without private keys", self.nodes[0].deriveaddresses, hardened_without_privkey_descriptor)
diff --git a/test/functional/rpc_estimatefee.py b/test/functional/rpc_estimatefee.py
index 51b7efb4c3..b057400887 100755
--- a/test/functional/rpc_estimatefee.py
+++ b/test/functional/rpc_estimatefee.py
@@ -22,15 +22,15 @@ class EstimateFeeTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "estimaterawfee", self.nodes[0].estimaterawfee)
# wrong type for conf_target
- assert_raises_rpc_error(-3, "Expected type number, got string", self.nodes[0].estimatesmartfee, 'foo')
- assert_raises_rpc_error(-3, "Expected type number, got string", self.nodes[0].estimaterawfee, 'foo')
+ assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].estimatesmartfee, 'foo')
+ assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].estimaterawfee, 'foo')
# wrong type for estimatesmartfee(estimate_mode)
- assert_raises_rpc_error(-3, "Expected type string, got number", self.nodes[0].estimatesmartfee, 1, 1)
+ assert_raises_rpc_error(-3, "JSON value of type number is not of expected type string", self.nodes[0].estimatesmartfee, 1, 1)
assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', self.nodes[0].estimatesmartfee, 1, 'foo')
# wrong type for estimaterawfee(threshold)
- assert_raises_rpc_error(-3, "Expected type number, got string", self.nodes[0].estimaterawfee, 1, 'foo')
+ assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].estimaterawfee, 1, 'foo')
# extra params
assert_raises_rpc_error(-1, "estimatesmartfee", self.nodes[0].estimatesmartfee, 1, 'ECONOMICAL', 1)
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 948deaaec4..9a3a356097 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -106,6 +106,8 @@ class RawTransactionsTest(BitcoinTestFramework):
self.generate(self.nodes[2], 1)
self.generate(self.nodes[0], 121)
+ self.test_add_inputs_default_value()
+ self.test_preset_inputs_selection()
self.test_weight_calculation()
self.test_change_position()
self.test_simple()
@@ -301,7 +303,7 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
- assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None})
+ assert_raises_rpc_error(-1, "JSON value of type null is not of expected type string", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None})
assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
rawtx = self.nodes[2].fundrawtransaction(rawtx, {'change_type': 'bech32'})
dec_tx = self.nodes[2].decoderawtransaction(rawtx['hex'])
@@ -408,7 +410,7 @@ class RawTransactionsTest(BitcoinTestFramework):
inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
outputs = { self.nodes[0].getnewaddress() : 1.0}
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
- assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx)
+ assert_raises_rpc_error(-4, "Unable to find UTXO for external input", self.nodes[2].fundrawtransaction, rawtx)
def test_fee_p2pkh(self):
"""Compare fee of a standard pubkeyhash transaction."""
@@ -635,7 +637,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.log.info("Test fundrawtxn fee with many inputs")
# Empty node1, send some small coins from node0 to node1.
- self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
+ self.nodes[1].sendall(recipients=[self.nodes[0].getnewaddress()])
self.generate(self.nodes[1], 1)
for _ in range(20):
@@ -661,7 +663,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.log.info("Test fundrawtxn sign+send with many inputs")
# Again, empty node1, send some small coins from node0 to node1.
- self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
+ self.nodes[1].sendall(recipients=[self.nodes[0].getnewaddress()])
self.generate(self.nodes[1], 1)
for _ in range(20):
@@ -1073,23 +1075,193 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[2].unloadwallet("extfund")
+ def test_add_inputs_default_value(self):
+ self.log.info("Test 'add_inputs' default value")
+
+ # Create and fund the wallet with 5 BTC
+ self.nodes[2].createwallet("test_preset_inputs")
+ wallet = self.nodes[2].get_wallet_rpc("test_preset_inputs")
+ addr1 = wallet.getnewaddress(address_type="bech32")
+ self.nodes[0].sendtoaddress(addr1, 5)
+ self.generate(self.nodes[0], 1)
+
+ # Covered cases:
+ # 1. Default add_inputs value with no preset inputs (add_inputs=true):
+ # Expect: automatically add coins from the wallet to the tx.
+ # 2. Default add_inputs value with preset inputs (add_inputs=false):
+ # Expect: disallow automatic coin selection.
+ # 3. Explicit add_inputs=true and preset inputs (with preset inputs not-covering the target amount).
+ # Expect: include inputs from the wallet.
+ # 4. Explicit add_inputs=true and preset inputs (with preset inputs covering the target amount).
+ # Expect: only preset inputs are used.
+ # 5. Explicit add_inputs=true, no preset inputs (same as (1) but with an explicit set):
+ # Expect: include inputs from the wallet.
+
+ # Case (1), 'send' command
+ # 'add_inputs' value is true unless "inputs" are specified, in such case, add_inputs=false.
+ # So, the wallet will automatically select coins and create the transaction if only the outputs are provided.
+ tx = wallet.send(outputs=[{addr1: 3}])
+ assert tx["complete"]
+
+ # Case (2), 'send' command
+ # Select an input manually, which doesn't cover the entire output amount and
+ # verify that the dynamically set 'add_inputs=false' value works.
+
+ # Fund wallet with 2 outputs, 5 BTC each.
+ addr2 = wallet.getnewaddress(address_type="bech32")
+ source_tx = self.nodes[0].send(outputs=[{addr1: 5}, {addr2: 5}], options={"change_position": 0})
+ self.generate(self.nodes[0], 1)
+
+ # Select only one input.
+ options = {
+ "inputs": [
+ {
+ "txid": source_tx["txid"],
+ "vout": 1 # change position was hardcoded to index 0
+ }
+ ]
+ }
+ assert_raises_rpc_error(-4, "Insufficient funds", wallet.send, outputs=[{addr1: 8}], options=options)
+
+ # Case (3), Explicit add_inputs=true and preset inputs (with preset inputs not-covering the target amount)
+ options["add_inputs"] = True
+ options["add_to_wallet"] = False
+ tx = wallet.send(outputs=[{addr1: 8}], options=options)
+ assert tx["complete"]
+
+ # Case (4), Explicit add_inputs=true and preset inputs (with preset inputs covering the target amount)
+ options["inputs"].append({
+ "txid": source_tx["txid"],
+ "vout": 2 # change position was hardcoded to index 0
+ })
+ tx = wallet.send(outputs=[{addr1: 8}], options=options)
+ assert tx["complete"]
+ # Check that only the preset inputs were added to the tx
+ decoded_psbt_inputs = self.nodes[0].decodepsbt(tx["psbt"])['tx']['vin']
+ assert_equal(len(decoded_psbt_inputs), 2)
+ for input in decoded_psbt_inputs:
+ assert_equal(input["txid"], source_tx["txid"])
+
+ # Case (5), assert that inputs are added to the tx by explicitly setting add_inputs=true
+ options = {"add_inputs": True, "add_to_wallet": True}
+ tx = wallet.send(outputs=[{addr1: 8}], options=options)
+ assert tx["complete"]
+
+ ################################################
+
+ # Case (1), 'walletcreatefundedpsbt' command
+ # Default add_inputs value with no preset inputs (add_inputs=true)
+ inputs = []
+ outputs = {self.nodes[1].getnewaddress(): 8}
+ assert "psbt" in wallet.walletcreatefundedpsbt(inputs=inputs, outputs=outputs)
+
+ # Case (2), 'walletcreatefundedpsbt' command
+ # Default add_inputs value with preset inputs (add_inputs=false).
+ inputs = [{
+ "txid": source_tx["txid"],
+ "vout": 1 # change position was hardcoded to index 0
+ }]
+ outputs = {self.nodes[1].getnewaddress(): 8}
+ assert_raises_rpc_error(-4, "Insufficient funds", wallet.walletcreatefundedpsbt, inputs=inputs, outputs=outputs)
+
+ # Case (3), Explicit add_inputs=true and preset inputs (with preset inputs not-covering the target amount)
+ options["add_inputs"] = True
+ options["add_to_wallet"] = False
+ assert "psbt" in wallet.walletcreatefundedpsbt(outputs=[{addr1: 8}], inputs=inputs, options=options)
+
+ # Case (4), Explicit add_inputs=true and preset inputs (with preset inputs covering the target amount)
+ inputs.append({
+ "txid": source_tx["txid"],
+ "vout": 2 # change position was hardcoded to index 0
+ })
+ psbt_tx = wallet.walletcreatefundedpsbt(outputs=[{addr1: 8}], inputs=inputs, options=options)
+ # Check that only the preset inputs were added to the tx
+ decoded_psbt_inputs = self.nodes[0].decodepsbt(psbt_tx["psbt"])['tx']['vin']
+ assert_equal(len(decoded_psbt_inputs), 2)
+ for input in decoded_psbt_inputs:
+ assert_equal(input["txid"], source_tx["txid"])
+
+ # Case (5), 'walletcreatefundedpsbt' command
+ # Explicit add_inputs=true, no preset inputs
+ options = {
+ "add_inputs": True
+ }
+ assert "psbt" in wallet.walletcreatefundedpsbt(inputs=[], outputs=outputs, options=options)
+
+ self.nodes[2].unloadwallet("test_preset_inputs")
+
+ def test_preset_inputs_selection(self):
+ self.log.info('Test wallet preset inputs are not double-counted or reused in coin selection')
+
+ # Create and fund the wallet with 4 UTXO of 5 BTC each (20 BTC total)
+ self.nodes[2].createwallet("test_preset_inputs_selection")
+ wallet = self.nodes[2].get_wallet_rpc("test_preset_inputs_selection")
+ outputs = {}
+ for _ in range(4):
+ outputs[wallet.getnewaddress(address_type="bech32")] = 5
+ self.nodes[0].sendmany("", outputs)
+ self.generate(self.nodes[0], 1)
+
+ # Select the preset inputs
+ coins = wallet.listunspent()
+ preset_inputs = [coins[0], coins[1], coins[2]]
+
+ # Now let's create the tx creation options
+ options = {
+ "inputs": preset_inputs,
+ "add_inputs": True, # automatically add coins from the wallet to fulfill the target
+ "subtract_fee_from_outputs": [0], # deduct fee from first output
+ "add_to_wallet": False
+ }
+
+ # Attempt to send 29 BTC from a wallet that only has 20 BTC. The wallet should exclude
+ # the preset inputs from the pool of available coins, realize that there is not enough
+ # money to fund the 29 BTC payment, and fail with "Insufficient funds".
+ #
+ # Even with SFFO, the wallet can only afford to send 20 BTC.
+ # If the wallet does not properly exclude preset inputs from the pool of available coins
+ # prior to coin selection, it may create a transaction that does not fund the full payment
+ # amount or, through SFFO, incorrectly reduce the recipient's amount by the difference
+ # between the original target and the wrongly counted inputs (in this case 9 BTC)
+ # so that the recipient's amount is no longer equal to the user's selected target of 29 BTC.
+
+ # First case, use 'subtract_fee_from_outputs = true'
+ assert_raises_rpc_error(-4, "Insufficient funds", wallet.send, outputs=[{wallet.getnewaddress(address_type="bech32"): 29}], options=options)
+
+ # Second case, don't use 'subtract_fee_from_outputs'
+ del options["subtract_fee_from_outputs"]
+ assert_raises_rpc_error(-4, "Insufficient funds", wallet.send, outputs=[{wallet.getnewaddress(address_type="bech32"): 29}], options=options)
+
+ self.nodes[2].unloadwallet("test_preset_inputs_selection")
+
def test_weight_calculation(self):
self.log.info("Test weight calculation with external inputs")
self.nodes[2].createwallet("test_weight_calculation")
wallet = self.nodes[2].get_wallet_rpc("test_weight_calculation")
- addr = wallet.getnewaddress()
- txid = self.nodes[0].sendtoaddress(addr, 5)
+ addr = wallet.getnewaddress(address_type="bech32")
+ ext_addr = self.nodes[0].getnewaddress(address_type="bech32")
+ txid = self.nodes[0].send([{addr: 5}, {ext_addr: 5}])["txid"]
vout = find_vout_for_address(self.nodes[0], txid, addr)
+ ext_vout = find_vout_for_address(self.nodes[0], txid, ext_addr)
- self.nodes[0].sendtoaddress(wallet.getnewaddress(), 5)
+ self.nodes[0].sendtoaddress(wallet.getnewaddress(address_type="bech32"), 5)
self.generate(self.nodes[0], 1)
- rawtx = wallet.createrawtransaction([{'txid': txid, 'vout': vout}], [{self.nodes[0].getnewaddress(): 9.999}])
- fundedtx = wallet.fundrawtransaction(rawtx, {'fee_rate': 10})
+ rawtx = wallet.createrawtransaction([{'txid': txid, 'vout': vout}], [{self.nodes[0].getnewaddress(address_type="bech32"): 8}])
+ fundedtx = wallet.fundrawtransaction(rawtx, {'fee_rate': 10, "change_type": "bech32"})
# with 71-byte signatures we should expect following tx size
- tx_size = 10 + 41*2 + 31*2 + (2 + 107*2)/4
+ # tx overhead (10) + 2 inputs (41 each) + 2 p2wpkh (31 each) + (segwit marker and flag (2) + 2 p2wpkh 71 byte sig witnesses (107 each)) / witness scaling factor (4)
+ tx_size = ceil(10 + 41*2 + 31*2 + (2 + 107*2)/4)
+ assert_equal(fundedtx['fee'] * COIN, tx_size * 10)
+
+ # Using the other output should have 72 byte sigs
+ rawtx = wallet.createrawtransaction([{'txid': txid, 'vout': ext_vout}], [{self.nodes[0].getnewaddress(): 13}])
+ ext_desc = self.nodes[0].getaddressinfo(ext_addr)["desc"]
+ fundedtx = wallet.fundrawtransaction(rawtx, {'fee_rate': 10, "change_type": "bech32", "solving_data": {"descriptors": [ext_desc]}})
+ # tx overhead (10) + 3 inputs (41 each) + 2 p2wpkh(31 each) + (segwit marker and flag (2) + 2 p2wpkh 71 bytes sig witnesses (107 each) + p2wpkh 72 byte sig witness (108)) / witness scaling factor (4)
+ tx_size = ceil(10 + 41*3 + 31*2 + (2 + 107*2 + 108)/4)
assert_equal(fundedtx['fee'] * COIN, tx_size * 10)
self.nodes[2].unloadwallet("test_weight_calculation")
diff --git a/test/functional/rpc_getblockfrompeer.py b/test/functional/rpc_getblockfrompeer.py
index a7628b5591..278a343b2b 100755
--- a/test/functional/rpc_getblockfrompeer.py
+++ b/test/functional/rpc_getblockfrompeer.py
@@ -54,14 +54,17 @@ class GetBlockFromPeerTest(BitcoinTestFramework):
assert_equal(len(peers), 1)
peer_0_peer_1_id = peers[0]["id"]
- self.log.info("Arguments must be sensible")
- assert_raises_rpc_error(-8, "hash must be of length 64 (not 4, for '1234')", self.nodes[0].getblockfrompeer, "1234", 0)
+ self.log.info("Arguments must be valid")
+ assert_raises_rpc_error(-8, "hash must be of length 64 (not 4, for '1234')", self.nodes[0].getblockfrompeer, "1234", peer_0_peer_1_id)
+ assert_raises_rpc_error(-3, "JSON value of type number is not of expected type string", self.nodes[0].getblockfrompeer, 1234, peer_0_peer_1_id)
+ assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].getblockfrompeer, short_tip, "0")
self.log.info("We must already have the header")
assert_raises_rpc_error(-1, "Block header missing", self.nodes[0].getblockfrompeer, "00" * 32, 0)
self.log.info("Non-existent peer generates error")
- assert_raises_rpc_error(-1, "Peer does not exist", self.nodes[0].getblockfrompeer, short_tip, peer_0_peer_1_id + 1)
+ for peer_id in [-1, peer_0_peer_1_id + 1]:
+ assert_raises_rpc_error(-1, "Peer does not exist", self.nodes[0].getblockfrompeer, short_tip, peer_id)
self.log.info("Fetching from pre-segwit peer generates error")
self.nodes[0].add_p2p_connection(P2PInterface(), services=P2P_SERVICES & ~NODE_WITNESS)
diff --git a/test/functional/rpc_getdescriptorinfo.py b/test/functional/rpc_getdescriptorinfo.py
index 5e6fd66aab..1b0f411e52 100755
--- a/test/functional/rpc_getdescriptorinfo.py
+++ b/test/functional/rpc_getdescriptorinfo.py
@@ -29,7 +29,7 @@ class DescriptorTest(BitcoinTestFramework):
def run_test(self):
assert_raises_rpc_error(-1, 'getdescriptorinfo', self.nodes[0].getdescriptorinfo)
- assert_raises_rpc_error(-3, 'Expected type string', self.nodes[0].getdescriptorinfo, 1)
+ assert_raises_rpc_error(-3, 'JSON value of type number is not of expected type string', self.nodes[0].getdescriptorinfo, 1)
assert_raises_rpc_error(-5, "'' is not a valid descriptor function", self.nodes[0].getdescriptorinfo, "")
# P2PK output with the specified public key.
diff --git a/test/functional/rpc_help.py b/test/functional/rpc_help.py
index 3b6413d4a6..5b7e724728 100755
--- a/test/functional/rpc_help.py
+++ b/test/functional/rpc_help.py
@@ -92,7 +92,7 @@ class HelpRpcTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, 'help', node.help, 'foo', 'bar')
# invalid argument
- assert_raises_rpc_error(-1, 'JSON value is not a string as expected', node.help, 0)
+ assert_raises_rpc_error(-1, "JSON value of type number is not of expected type string", node.help, 0)
# help of unknown command
assert_equal(node.help('foo'), 'help: unknown command: foo')
diff --git a/test/functional/rpc_invalidateblock.py b/test/functional/rpc_invalidateblock.py
index f1c2537ef9..1e33e7ca9c 100755
--- a/test/functional/rpc_invalidateblock.py
+++ b/test/functional/rpc_invalidateblock.py
@@ -8,6 +8,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR
from test_framework.util import (
assert_equal,
+ assert_raises_rpc_error,
)
@@ -83,6 +84,10 @@ class InvalidateTest(BitcoinTestFramework):
# Should be back at the tip by now
assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
+ self.log.info("Verify that invalidating an unknown block throws an error")
+ assert_raises_rpc_error(-5, "Block not found", self.nodes[1].invalidateblock, "00" * 32)
+ assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
+
if __name__ == '__main__':
InvalidateTest().main()
diff --git a/test/functional/rpc_mempool_info.py b/test/functional/rpc_mempool_info.py
index cd7a48d387..9b5a3b9112 100755
--- a/test/functional/rpc_mempool_info.py
+++ b/test/functional/rpc_mempool_info.py
@@ -4,7 +4,6 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test RPCs that retrieve information from the mempool."""
-from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -19,7 +18,6 @@ class RPCMempoolInfoTest(BitcoinTestFramework):
def run_test(self):
self.wallet = MiniWallet(self.nodes[0])
- self.generate(self.wallet, COINBASE_MATURITY + 1)
self.wallet.rescan_utxos()
confirmed_utxo = self.wallet.get_utxo()
diff --git a/test/functional/rpc_packages.py b/test/functional/rpc_packages.py
index 63533affd0..9a563cbf5f 100755
--- a/test/functional/rpc_packages.py
+++ b/test/functional/rpc_packages.py
@@ -10,21 +10,25 @@ import random
from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE
from test_framework.test_framework import BitcoinTestFramework
from test_framework.messages import (
- BIP125_SEQUENCE_NUMBER,
+ MAX_BIP125_RBF_SEQUENCE,
COIN,
CTxInWitness,
tx_from_hex,
)
+from test_framework.p2p import P2PTxInvStore
from test_framework.script import (
CScript,
OP_TRUE,
)
from test_framework.util import (
assert_equal,
+ assert_fee_amount,
+ assert_raises_rpc_error,
)
from test_framework.wallet import (
create_child_with_parents,
create_raw_chain,
+ DEFAULT_FEE,
make_chain,
)
@@ -51,7 +55,7 @@ class RPCPackagesTest(BitcoinTestFramework):
self.address = node.get_deterministic_priv_key().address
self.coins = []
# The last 100 coinbase transactions are premature
- for b in self.generatetoaddress(node, 200, self.address)[:100]:
+ for b in self.generatetoaddress(node, 220, self.address)[:-100]:
coinbase = node.getblock(blockhash=b, verbosity=2)["tx"][0]
self.coins.append({
"txid": coinbase["txid"],
@@ -82,7 +86,7 @@ class RPCPackagesTest(BitcoinTestFramework):
self.test_multiple_parents()
self.test_conflicting()
self.test_rbf()
-
+ self.test_submitpackage()
def test_independent(self):
self.log.info("Test multiple independent transactions in a package")
@@ -132,8 +136,7 @@ class RPCPackagesTest(BitcoinTestFramework):
def test_chain(self):
node = self.nodes[0]
- first_coin = self.coins.pop()
- (chain_hex, chain_txns) = create_raw_chain(node, first_coin, self.address, self.privkeys)
+ (chain_hex, chain_txns) = create_raw_chain(node, self.coins.pop(), self.address, self.privkeys)
self.log.info("Check that testmempoolaccept requires packages to be sorted by dependency")
assert_equal(node.testmempoolaccept(rawtxs=chain_hex[::-1]),
[{"txid": tx.rehash(), "wtxid": tx.getwtxid(), "package-error": "package-not-sorted"} for tx in chain_txns[::-1]])
@@ -270,7 +273,7 @@ class RPCPackagesTest(BitcoinTestFramework):
def test_rbf(self):
node = self.nodes[0]
coin = self.coins.pop()
- inputs = [{"txid": coin["txid"], "vout": 0, "sequence": BIP125_SEQUENCE_NUMBER}]
+ inputs = [{"txid": coin["txid"], "vout": 0, "sequence": MAX_BIP125_RBF_SEQUENCE}]
fee = Decimal('0.00125000')
output = {node.get_deterministic_priv_key().address: 50 - fee}
raw_replaceable_tx = node.createrawtransaction(inputs, output)
@@ -306,5 +309,127 @@ class RPCPackagesTest(BitcoinTestFramework):
}]
self.assert_testres_equal(self.independent_txns_hex + [signed_replacement_tx["hex"]], testres_rbf_package)
+ def assert_equal_package_results(self, node, testmempoolaccept_result, submitpackage_result):
+ """Assert that a successful submitpackage result is consistent with testmempoolaccept
+ results and getmempoolentry info. Note that the result structs are different and, due to
+ policy differences between testmempoolaccept and submitpackage (i.e. package feerate),
+ some information may be different.
+ """
+ for testres_tx in testmempoolaccept_result:
+ # Grab this result from the submitpackage_result
+ submitres_tx = submitpackage_result["tx-results"][testres_tx["wtxid"]]
+ assert_equal(submitres_tx["txid"], testres_tx["txid"])
+ # No "allowed" if the tx was already in the mempool
+ if "allowed" in testres_tx and testres_tx["allowed"]:
+ assert_equal(submitres_tx["vsize"], testres_tx["vsize"])
+ assert_equal(submitres_tx["fees"]["base"], testres_tx["fees"]["base"])
+ entry_info = node.getmempoolentry(submitres_tx["txid"])
+ assert_equal(submitres_tx["vsize"], entry_info["vsize"])
+ assert_equal(submitres_tx["fees"]["base"], entry_info["fees"]["base"])
+
+ def test_submit_child_with_parents(self, num_parents, partial_submit):
+ node = self.nodes[0]
+ peer = node.add_p2p_connection(P2PTxInvStore())
+ # Test a package with num_parents parents and 1 child transaction.
+ package_hex = []
+ package_txns = []
+ values = []
+ scripts = []
+ for _ in range(num_parents):
+ parent_coin = self.coins.pop()
+ value = parent_coin["amount"]
+ (tx, txhex, value, spk) = make_chain(node, self.address, self.privkeys, parent_coin["txid"], value)
+ package_hex.append(txhex)
+ package_txns.append(tx)
+ values.append(value)
+ scripts.append(spk)
+ if partial_submit and random.choice([True, False]):
+ node.sendrawtransaction(txhex)
+ child_hex = create_child_with_parents(node, self.address, self.privkeys, package_txns, values, scripts)
+ package_hex.append(child_hex)
+ package_txns.append(tx_from_hex(child_hex))
+
+ testmempoolaccept_result = node.testmempoolaccept(rawtxs=package_hex)
+ submitpackage_result = node.submitpackage(package=package_hex)
+
+ # Check that each result is present, with the correct size and fees
+ for i in range(num_parents + 1):
+ tx = package_txns[i]
+ wtxid = tx.getwtxid()
+ assert wtxid in submitpackage_result["tx-results"]
+ tx_result = submitpackage_result["tx-results"][wtxid]
+ assert_equal(tx_result, {
+ "txid": tx.rehash(),
+ "vsize": tx.get_vsize(),
+ "fees": {
+ "base": DEFAULT_FEE,
+ }
+ })
+
+ # submitpackage result should be consistent with testmempoolaccept and getmempoolentry
+ self.assert_equal_package_results(node, testmempoolaccept_result, submitpackage_result)
+
+ # Package feerate is calculated for the remaining transactions after deduplication and
+ # individual submission. If only 0 or 1 transaction is left, e.g. because all transactions
+ # had high-feerates or were already in the mempool, no package feerate is provided.
+ # In this case, since all of the parents have high fees, each is accepted individually.
+ assert "package-feerate" not in submitpackage_result
+
+ # The node should announce each transaction. No guarantees for propagation.
+ peer.wait_for_broadcast([tx.getwtxid() for tx in package_txns])
+ self.generate(node, 1)
+
+
+ def test_submit_cpfp(self):
+ node = self.nodes[0]
+ peer = node.add_p2p_connection(P2PTxInvStore())
+
+ # 2 parent 1 child CPFP. First parent pays high fees, second parent pays 0 fees and is
+ # fee-bumped by the child.
+ coin_rich = self.coins.pop()
+ coin_poor = self.coins.pop()
+ tx_rich, hex_rich, value_rich, spk_rich = make_chain(node, self.address, self.privkeys, coin_rich["txid"], coin_rich["amount"])
+ tx_poor, hex_poor, value_poor, spk_poor = make_chain(node, self.address, self.privkeys, coin_poor["txid"], coin_poor["amount"], fee=0)
+ package_txns = [tx_rich, tx_poor]
+ hex_child = create_child_with_parents(node, self.address, self.privkeys, package_txns, [value_rich, value_poor], [spk_rich, spk_poor])
+ tx_child = tx_from_hex(hex_child)
+ package_txns.append(tx_child)
+
+ submitpackage_result = node.submitpackage([hex_rich, hex_poor, hex_child])
+
+ rich_parent_result = submitpackage_result["tx-results"][tx_rich.getwtxid()]
+ poor_parent_result = submitpackage_result["tx-results"][tx_poor.getwtxid()]
+ child_result = submitpackage_result["tx-results"][tx_child.getwtxid()]
+ assert_equal(rich_parent_result["fees"]["base"], DEFAULT_FEE)
+ assert_equal(poor_parent_result["fees"]["base"], 0)
+ assert_equal(child_result["fees"]["base"], DEFAULT_FEE)
+ # Package feerate is calculated for the remaining transactions after deduplication and
+ # individual submission. Since this package had a 0-fee parent, package feerate must have
+ # been used and returned.
+ assert "package-feerate" in submitpackage_result
+ assert_fee_amount(DEFAULT_FEE, rich_parent_result["vsize"] + child_result["vsize"], submitpackage_result["package-feerate"])
+
+ # The node will broadcast each transaction, still abiding by its peer's fee filter
+ peer.wait_for_broadcast([tx.getwtxid() for tx in package_txns])
+ self.generate(node, 1)
+
+
+ def test_submitpackage(self):
+ node = self.nodes[0]
+
+ self.log.info("Submitpackage valid packages with 1 child and some number of parents")
+ for num_parents in [1, 2, 24]:
+ self.test_submit_child_with_parents(num_parents, False)
+ self.test_submit_child_with_parents(num_parents, True)
+
+ self.log.info("Submitpackage valid packages with CPFP")
+ self.test_submit_cpfp()
+
+ self.log.info("Submitpackage only allows packages of 1 child with its parents")
+ # Chain of 3 transactions has too many generations
+ chain_hex, _ = create_raw_chain(node, self.coins.pop(), self.address, self.privkeys, 3)
+ assert_raises_rpc_error(-25, "not-child-with-parents", node.submitpackage, chain_hex)
+
+
if __name__ == "__main__":
RPCPackagesTest().main()
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 444e56610e..1fe3b21542 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -9,10 +9,25 @@ from decimal import Decimal
from itertools import product
from test_framework.descriptors import descsum_create
-from test_framework.key import ECKey
+from test_framework.key import ECKey, H_POINT
from test_framework.messages import (
- ser_compact_size,
+ COutPoint,
+ CTransaction,
+ CTxIn,
+ CTxOut,
+ MAX_BIP125_RBF_SEQUENCE,
WITNESS_SCALE_FACTOR,
+ ser_compact_size,
+)
+from test_framework.psbt import (
+ PSBT,
+ PSBTMap,
+ PSBT_GLOBAL_UNSIGNED_TX,
+ PSBT_IN_RIPEMD160,
+ PSBT_IN_SHA256,
+ PSBT_IN_HASH160,
+ PSBT_IN_HASH256,
+ PSBT_OUT_TAP_TREE,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -21,13 +36,14 @@ from test_framework.util import (
assert_greater_than,
assert_raises_rpc_error,
find_output,
+ find_vout_for_address,
+ random_bytes,
)
from test_framework.wallet_util import bytes_to_wif
import json
import os
-MAX_BIP125_RBF_SEQUENCE = 0xfffffffd
# Create one-input, one-output, no-fee transaction:
class PSBTTest(BitcoinTestFramework):
@@ -435,6 +451,7 @@ class PSBTTest(BitcoinTestFramework):
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_psbt.json'), encoding='utf-8') as f:
d = json.load(f)
invalids = d['invalid']
+ invalid_with_msgs = d["invalid_with_msg"]
valids = d['valid']
creators = d['creator']
signers = d['signer']
@@ -445,6 +462,9 @@ class PSBTTest(BitcoinTestFramework):
# Invalid PSBTs
for invalid in invalids:
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decodepsbt, invalid)
+ for invalid in invalid_with_msgs:
+ psbt, msg = invalid
+ assert_raises_rpc_error(-22, f"TX decode failed {msg}", self.nodes[0].decodepsbt, psbt)
# Valid PSBTs
for valid in valids:
@@ -452,7 +472,7 @@ class PSBTTest(BitcoinTestFramework):
# Creator Tests
for creator in creators:
- created_tx = self.nodes[0].createpsbt(creator['inputs'], creator['outputs'])
+ created_tx = self.nodes[0].createpsbt(inputs=creator['inputs'], outputs=creator['outputs'], replaceable=False)
assert_equal(created_tx, creator['result'])
# Signer tests
@@ -723,5 +743,115 @@ class PSBTTest(BitcoinTestFramework):
)
assert_equal(psbt2["fee"], psbt3["fee"])
+ self.log.info("Test signing inputs that the wallet has keys for but is not watching the scripts")
+ self.nodes[1].createwallet(wallet_name="scriptwatchonly", disable_private_keys=True)
+ watchonly = self.nodes[1].get_wallet_rpc("scriptwatchonly")
+
+ eckey = ECKey()
+ eckey.generate()
+ privkey = bytes_to_wif(eckey.get_bytes())
+
+ desc = descsum_create("wsh(pkh({}))".format(eckey.get_pubkey().get_bytes().hex()))
+ if self.options.descriptors:
+ res = watchonly.importdescriptors([{"desc": desc, "timestamp": "now"}])
+ else:
+ res = watchonly.importmulti([{"desc": desc, "timestamp": "now"}])
+ assert res[0]["success"]
+ addr = self.nodes[0].deriveaddresses(desc)[0]
+ self.nodes[0].sendtoaddress(addr, 10)
+ self.generate(self.nodes[0], 1)
+ self.nodes[0].importprivkey(privkey)
+
+ psbt = watchonly.sendall([wallet.getnewaddress()])["psbt"]
+ psbt = self.nodes[0].walletprocesspsbt(psbt)["psbt"]
+ self.nodes[0].sendrawtransaction(self.nodes[0].finalizepsbt(psbt)["hex"])
+
+ # Same test but for taproot
+ if self.options.descriptors:
+ eckey = ECKey()
+ eckey.generate()
+ privkey = bytes_to_wif(eckey.get_bytes())
+
+ desc = descsum_create("tr({},pk({}))".format(H_POINT, eckey.get_pubkey().get_bytes().hex()))
+ res = watchonly.importdescriptors([{"desc": desc, "timestamp": "now"}])
+ assert res[0]["success"]
+ addr = self.nodes[0].deriveaddresses(desc)[0]
+ self.nodes[0].sendtoaddress(addr, 10)
+ self.generate(self.nodes[0], 1)
+ self.nodes[0].importdescriptors([{"desc": descsum_create("tr({})".format(privkey)), "timestamp":"now"}])
+
+ psbt = watchonly.sendall([wallet.getnewaddress(), addr])["psbt"]
+ psbt = self.nodes[0].walletprocesspsbt(psbt)["psbt"]
+ txid = self.nodes[0].sendrawtransaction(self.nodes[0].finalizepsbt(psbt)["hex"])
+ vout = find_vout_for_address(self.nodes[0], txid, addr)
+
+ # Make sure tap tree is in psbt
+ parsed_psbt = PSBT.from_base64(psbt)
+ assert_greater_than(len(parsed_psbt.o[vout].map[PSBT_OUT_TAP_TREE]), 0)
+ assert "taproot_tree" in self.nodes[0].decodepsbt(psbt)["outputs"][vout]
+ parsed_psbt.make_blank()
+ comb_psbt = self.nodes[0].combinepsbt([psbt, parsed_psbt.to_base64()])
+ assert_equal(comb_psbt, psbt)
+
+ self.log.info("Test that walletprocesspsbt both updates and signs a non-updated psbt containing Taproot inputs")
+ addr = self.nodes[0].getnewaddress("", "bech32m")
+ txid = self.nodes[0].sendtoaddress(addr, 1)
+ vout = find_vout_for_address(self.nodes[0], txid, addr)
+ psbt = self.nodes[0].createpsbt([{"txid": txid, "vout": vout}], [{self.nodes[0].getnewaddress(): 0.9999}])
+ signed = self.nodes[0].walletprocesspsbt(psbt)
+ rawtx = self.nodes[0].finalizepsbt(signed["psbt"])["hex"]
+ self.nodes[0].sendrawtransaction(rawtx)
+ self.generate(self.nodes[0], 1)
+
+ # Make sure tap tree is not in psbt
+ parsed_psbt = PSBT.from_base64(psbt)
+ assert PSBT_OUT_TAP_TREE not in parsed_psbt.o[0].map
+ assert "taproot_tree" not in self.nodes[0].decodepsbt(psbt)["outputs"][0]
+ parsed_psbt.make_blank()
+ comb_psbt = self.nodes[0].combinepsbt([psbt, parsed_psbt.to_base64()])
+ assert_equal(comb_psbt, psbt)
+
+ self.log.info("Test decoding PSBT with per-input preimage types")
+ # note that the decodepsbt RPC doesn't check whether preimages and hashes match
+ hash_ripemd160, preimage_ripemd160 = random_bytes(20), random_bytes(50)
+ hash_sha256, preimage_sha256 = random_bytes(32), random_bytes(50)
+ hash_hash160, preimage_hash160 = random_bytes(20), random_bytes(50)
+ hash_hash256, preimage_hash256 = random_bytes(32), random_bytes(50)
+
+ tx = CTransaction()
+ tx.vin = [CTxIn(outpoint=COutPoint(hash=int('aa' * 32, 16), n=0), scriptSig=b""),
+ CTxIn(outpoint=COutPoint(hash=int('bb' * 32, 16), n=0), scriptSig=b""),
+ CTxIn(outpoint=COutPoint(hash=int('cc' * 32, 16), n=0), scriptSig=b""),
+ CTxIn(outpoint=COutPoint(hash=int('dd' * 32, 16), n=0), scriptSig=b"")]
+ tx.vout = [CTxOut(nValue=0, scriptPubKey=b"")]
+ psbt = PSBT()
+ psbt.g = PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()})
+ psbt.i = [PSBTMap({bytes([PSBT_IN_RIPEMD160]) + hash_ripemd160: preimage_ripemd160}),
+ PSBTMap({bytes([PSBT_IN_SHA256]) + hash_sha256: preimage_sha256}),
+ PSBTMap({bytes([PSBT_IN_HASH160]) + hash_hash160: preimage_hash160}),
+ PSBTMap({bytes([PSBT_IN_HASH256]) + hash_hash256: preimage_hash256})]
+ psbt.o = [PSBTMap()]
+ res_inputs = self.nodes[0].decodepsbt(psbt.to_base64())["inputs"]
+ assert_equal(len(res_inputs), 4)
+ preimage_keys = ["ripemd160_preimages", "sha256_preimages", "hash160_preimages", "hash256_preimages"]
+ expected_hashes = [hash_ripemd160, hash_sha256, hash_hash160, hash_hash256]
+ expected_preimages = [preimage_ripemd160, preimage_sha256, preimage_hash160, preimage_hash256]
+ for res_input, preimage_key, hash, preimage in zip(res_inputs, preimage_keys, expected_hashes, expected_preimages):
+ assert preimage_key in res_input
+ assert_equal(len(res_input[preimage_key]), 1)
+ assert hash.hex() in res_input[preimage_key]
+ assert_equal(res_input[preimage_key][hash.hex()], preimage.hex())
+
+ self.log.info("Test that combining PSBTs with different transactions fails")
+ tx = CTransaction()
+ tx.vin = [CTxIn(outpoint=COutPoint(hash=int('aa' * 32, 16), n=0), scriptSig=b"")]
+ tx.vout = [CTxOut(nValue=0, scriptPubKey=b"")]
+ psbt1 = PSBT(g=PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()}), i=[PSBTMap()], o=[PSBTMap()]).to_base64()
+ tx.vout[0].nValue += 1 # slightly modify tx
+ psbt2 = PSBT(g=PSBTMap({PSBT_GLOBAL_UNSIGNED_TX: tx.serialize()}), i=[PSBTMap()], o=[PSBTMap()]).to_base64()
+ assert_raises_rpc_error(-8, "PSBTs not compatible (different transactions)", self.nodes[0].combinepsbt, [psbt1, psbt2])
+ assert_equal(self.nodes[0].combinepsbt([psbt1, psbt1]), psbt1)
+
+
if __name__ == '__main__':
PSBTTest().main()
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index 26a5da85b7..f1fae13b4a 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -17,7 +17,7 @@ from decimal import Decimal
from test_framework.blocktools import COINBASE_MATURITY
from test_framework.messages import (
- BIP125_SEQUENCE_NUMBER,
+ MAX_BIP125_RBF_SEQUENCE,
CTransaction,
tx_from_hex,
)
@@ -124,13 +124,13 @@ class RawTransactionsTest(BitcoinTestFramework):
# 6. invalid parameters - supply txid and invalid boolean values (strings) for verbose
for value in ["True", "False"]:
- assert_raises_rpc_error(-1, "not a boolean", self.nodes[n].getrawtransaction, txid=txId, verbose=value)
+ assert_raises_rpc_error(-1, "not of expected type bool", self.nodes[n].getrawtransaction, txid=txId, verbose=value)
# 7. invalid parameters - supply txid and empty array
- assert_raises_rpc_error(-1, "not a boolean", self.nodes[n].getrawtransaction, txId, [])
+ assert_raises_rpc_error(-1, "not of expected type bool", self.nodes[n].getrawtransaction, txId, [])
# 8. invalid parameters - supply txid and empty dict
- assert_raises_rpc_error(-1, "not a boolean", self.nodes[n].getrawtransaction, txId, {})
+ assert_raises_rpc_error(-1, "not of expected type bool", self.nodes[n].getrawtransaction, txId, {})
# Make a tx by sending, then generate 2 blocks; block1 has the tx in it
tx = self.wallet.send_self_transfer(from_node=self.nodes[2])['txid']
@@ -152,7 +152,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# We should not get the tx if we provide an unrelated block
assert_raises_rpc_error(-5, "No such transaction found", self.nodes[n].getrawtransaction, txid=tx, blockhash=block2)
# An invalid block hash should raise the correct errors
- assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[n].getrawtransaction, txid=tx, blockhash=True)
+ assert_raises_rpc_error(-1, "JSON value of type bool is not of expected type string", self.nodes[n].getrawtransaction, txid=tx, blockhash=True)
assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 6, for 'foobar')", self.nodes[n].getrawtransaction, txid=tx, blockhash="foobar")
assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 8, for 'abcd1234')", self.nodes[n].getrawtransaction, txid=tx, blockhash="abcd1234")
foo = "ZZZ0000000000000000000000000000000000000000000000000000000000000"
@@ -180,9 +180,9 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [], {}, 0, False, 'foo')
# Test `createrawtransaction` invalid `inputs`
- assert_raises_rpc_error(-3, "Expected type array", self.nodes[0].createrawtransaction, 'foo', {})
- assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, ['foo'], {})
- assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].createrawtransaction, [{}], {})
+ assert_raises_rpc_error(-3, "JSON value of type string is not of expected type array", self.nodes[0].createrawtransaction, 'foo', {})
+ assert_raises_rpc_error(-1, "JSON value of type string is not of expected type object", self.nodes[0].createrawtransaction, ['foo'], {})
+ assert_raises_rpc_error(-1, "JSON value of type null is not of expected type string", self.nodes[0].createrawtransaction, [{}], {})
assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {})
txid = "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844"
assert_raises_rpc_error(-8, f"txid must be hexadecimal string (not '{txid}')", self.nodes[0].createrawtransaction, [{'txid': txid}], {})
@@ -207,7 +207,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# Test `createrawtransaction` invalid `outputs`
address = getnewdestination()[2]
- assert_raises_rpc_error(-1, "JSON value is not an array as expected", self.nodes[0].createrawtransaction, [], 'foo')
+ assert_raises_rpc_error(-1, "JSON value of type string is not of expected type array", self.nodes[0].createrawtransaction, [], 'foo')
self.nodes[0].createrawtransaction(inputs=[], outputs={}) # Should not throw for backwards compatibility
self.nodes[0].createrawtransaction(inputs=[], outputs=[])
assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'})
@@ -223,15 +223,15 @@ class RawTransactionsTest(BitcoinTestFramework):
# Test `createrawtransaction` mismatch between sequence number(s) and `replaceable` option
assert_raises_rpc_error(-8, "Invalid parameter combination: Sequence number(s) contradict replaceable option",
- self.nodes[0].createrawtransaction, [{'txid': TXID, 'vout': 0, 'sequence': BIP125_SEQUENCE_NUMBER+1}], {}, 0, True)
+ self.nodes[0].createrawtransaction, [{'txid': TXID, 'vout': 0, 'sequence': MAX_BIP125_RBF_SEQUENCE+1}], {}, 0, True)
# Test `createrawtransaction` invalid `locktime`
- assert_raises_rpc_error(-3, "Expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo')
+ assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo')
assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, -1)
assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, 4294967296)
# Test `createrawtransaction` invalid `replaceable`
- assert_raises_rpc_error(-3, "Expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo')
+ assert_raises_rpc_error(-3, "JSON value of type string is not of expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo')
# Test that createrawtransaction accepts an array and object as outputs
# One output
diff --git a/test/functional/rpc_signer.py b/test/functional/rpc_signer.py
index f1107197c5..de17b2b929 100755
--- a/test/functional/rpc_signer.py
+++ b/test/functional/rpc_signer.py
@@ -77,10 +77,7 @@ class RPCSignerTest(BitcoinTestFramework):
)
self.clear_mock_result(self.nodes[1])
- result = self.nodes[1].enumeratesigners()
- assert_equal(len(result['signers']), 2)
- assert_equal(result['signers'][0]["fingerprint"], "00000001")
- assert_equal(result['signers'][0]["name"], "trezor_t")
+ assert_equal({'fingerprint': '00000001', 'name': 'trezor_t'} in self.nodes[1].enumeratesigners()['signers'], True)
if __name__ == '__main__':
RPCSignerTest().main()
diff --git a/test/functional/rpc_signmessagewithprivkey.py b/test/functional/rpc_signmessagewithprivkey.py
index 80555eab75..6635da150f 100755
--- a/test/functional/rpc_signmessagewithprivkey.py
+++ b/test/functional/rpc_signmessagewithprivkey.py
@@ -4,27 +4,44 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test RPC commands for signing messages with private key."""
+from test_framework.descriptors import (
+ descsum_create,
+)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
)
+
class SignMessagesWithPrivTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
+ def addresses_from_privkey(self, priv_key):
+ '''Return addresses for a given WIF private key in legacy (P2PKH),
+ nested segwit (P2SH-P2WPKH) and native segwit (P2WPKH) formats.'''
+ descriptors = f'pkh({priv_key})', f'sh(wpkh({priv_key}))', f'wpkh({priv_key})'
+ return [self.nodes[0].deriveaddresses(descsum_create(desc))[0] for desc in descriptors]
+
def run_test(self):
message = 'This is just a test message'
self.log.info('test signing with priv_key')
priv_key = 'cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N'
- address = 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB'
expected_signature = 'INbVnW4e6PeRmsv2Qgu8NuopvrVjkcxob+sX8OcZG0SALhWybUjzMLPdAsXI46YZGb0KQTRii+wWIQzRpG/U+S0='
signature = self.nodes[0].signmessagewithprivkey(priv_key, message)
assert_equal(expected_signature, signature)
- assert self.nodes[0].verifymessage(address, signature, message)
+
+ self.log.info('test that verifying with P2PKH address succeeds')
+ addresses = self.addresses_from_privkey(priv_key)
+ assert_equal(addresses[0], 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB')
+ assert self.nodes[0].verifymessage(addresses[0], signature, message)
+
+ self.log.info('test that verifying with non-P2PKH addresses throws error')
+ for non_p2pkh_address in addresses[1:]:
+ assert_raises_rpc_error(-3, "Address does not refer to key", self.nodes[0].verifymessage, non_p2pkh_address, signature, message)
self.log.info('test parameter validity and error codes')
# signmessagewithprivkey has two required parameters
@@ -41,5 +58,6 @@ class SignMessagesWithPrivTest(BitcoinTestFramework):
# malformed signature provided
assert_raises_rpc_error(-3, "Malformed base64 encoding", self.nodes[0].verifymessage, 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB', "invalid_sig", message)
+
if __name__ == '__main__':
SignMessagesWithPrivTest().main()
diff --git a/test/functional/rpc_signrawtransactionwithkey.py b/test/functional/rpc_signrawtransactionwithkey.py
new file mode 100755
index 0000000000..0da5a99fdb
--- /dev/null
+++ b/test/functional/rpc_signrawtransactionwithkey.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+# Copyright (c) 2015-2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test transaction signing using the signrawtransactionwithkey RPC."""
+
+from test_framework.blocktools import (
+ COINBASE_MATURITY,
+)
+from test_framework.address import (
+ script_to_p2sh,
+)
+from test_framework.key import ECKey
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ find_vout_for_address,
+)
+from test_framework.script_util import (
+ key_to_p2pk_script,
+ key_to_p2pkh_script,
+ script_to_p2sh_p2wsh_script,
+ script_to_p2wsh_script,
+)
+from test_framework.wallet_util import (
+ bytes_to_wif,
+)
+
+from decimal import (
+ Decimal,
+)
+from test_framework.wallet import (
+ getnewdestination,
+)
+
+
+class SignRawTransactionWithKeyTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 2
+
+ def send_to_address(self, addr, amount):
+ input = {"txid": self.nodes[0].getblock(self.block_hash[self.blk_idx])["tx"][0], "vout": 0}
+ output = {addr: amount}
+ self.blk_idx += 1
+ rawtx = self.nodes[0].createrawtransaction([input], output)
+ txid = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransactionwithkey(rawtx, [self.nodes[0].get_deterministic_priv_key().key])["hex"], 0)
+ return txid
+
+ def successful_signing_test(self):
+ """Create and sign a valid raw transaction with one input.
+
+ Expected results:
+
+ 1) The transaction has a complete set of signatures
+ 2) No script verification error occurred"""
+ self.log.info("Test valid raw transaction with one input")
+ privKeys = ['cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N', 'cVKpPfVKSJxKqVpE9awvXNWuLHCa5j5tiE7K6zbUSptFpTEtiFrA']
+
+ inputs = [
+ # Valid pay-to-pubkey scripts
+ {'txid': '9b907ef1e3c26fc71fe4a4b3580bc75264112f95050014157059c736f0202e71', 'vout': 0,
+ 'scriptPubKey': '76a91460baa0f494b38ce3c940dea67f3804dc52d1fb9488ac'},
+ {'txid': '83a4f6a6b73660e13ee6cb3c6063fa3759c50c9b7521d0536022961898f4fb02', 'vout': 0,
+ 'scriptPubKey': '76a914669b857c03a5ed269d5d85a1ffac9ed5d663072788ac'},
+ ]
+
+ outputs = {'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB': 0.1}
+
+ rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
+ rawTxSigned = self.nodes[0].signrawtransactionwithkey(rawTx, privKeys, inputs)
+
+ # 1) The transaction has a complete set of signatures
+ assert rawTxSigned['complete']
+
+ # 2) No script verification error occurred
+ assert 'errors' not in rawTxSigned
+
+ def witness_script_test(self):
+ self.log.info("Test signing transaction to P2SH-P2WSH addresses without wallet")
+ # Create a new P2SH-P2WSH 1-of-1 multisig address:
+ eckey = ECKey()
+ eckey.generate()
+ embedded_privkey = bytes_to_wif(eckey.get_bytes())
+ embedded_pubkey = eckey.get_pubkey().get_bytes().hex()
+ p2sh_p2wsh_address = self.nodes[1].createmultisig(1, [embedded_pubkey], "p2sh-segwit")
+ # send transaction to P2SH-P2WSH 1-of-1 multisig address
+ self.block_hash = self.generate(self.nodes[0], COINBASE_MATURITY + 1)
+ self.blk_idx = 0
+ self.send_to_address(p2sh_p2wsh_address["address"], 49.999)
+ self.generate(self.nodes[0], 1)
+ # Get the UTXO info from scantxoutset
+ unspent_output = self.nodes[1].scantxoutset('start', [p2sh_p2wsh_address['descriptor']])['unspents'][0]
+ spk = script_to_p2sh_p2wsh_script(p2sh_p2wsh_address['redeemScript']).hex()
+ unspent_output['witnessScript'] = p2sh_p2wsh_address['redeemScript']
+ unspent_output['redeemScript'] = script_to_p2wsh_script(unspent_output['witnessScript']).hex()
+ assert_equal(spk, unspent_output['scriptPubKey'])
+ # Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys
+ spending_tx = self.nodes[0].createrawtransaction([unspent_output], {getnewdestination()[2]: Decimal("49.998")})
+ spending_tx_signed = self.nodes[0].signrawtransactionwithkey(spending_tx, [embedded_privkey], [unspent_output])
+ # Check the signing completed successfully
+ assert 'complete' in spending_tx_signed
+ assert_equal(spending_tx_signed['complete'], True)
+
+ # Now test with P2PKH and P2PK scripts as the witnessScript
+ for tx_type in ['P2PKH', 'P2PK']: # these tests are order-independent
+ self.verify_txn_with_witness_script(tx_type)
+
+ def verify_txn_with_witness_script(self, tx_type):
+ self.log.info("Test with a {} script as the witnessScript".format(tx_type))
+ eckey = ECKey()
+ eckey.generate()
+ embedded_privkey = bytes_to_wif(eckey.get_bytes())
+ embedded_pubkey = eckey.get_pubkey().get_bytes().hex()
+ witness_script = {
+ 'P2PKH': key_to_p2pkh_script(embedded_pubkey).hex(),
+ 'P2PK': key_to_p2pk_script(embedded_pubkey).hex()
+ }.get(tx_type, "Invalid tx_type")
+ redeem_script = script_to_p2wsh_script(witness_script).hex()
+ addr = script_to_p2sh(redeem_script)
+ script_pub_key = self.nodes[1].validateaddress(addr)['scriptPubKey']
+ # Fund that address
+ txid = self.send_to_address(addr, 10)
+ vout = find_vout_for_address(self.nodes[0], txid, addr)
+ self.generate(self.nodes[0], 1)
+ # Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys
+ spending_tx = self.nodes[0].createrawtransaction([{'txid': txid, 'vout': vout}], {getnewdestination()[2]: Decimal("9.999")})
+ spending_tx_signed = self.nodes[0].signrawtransactionwithkey(spending_tx, [embedded_privkey], [{'txid': txid, 'vout': vout, 'scriptPubKey': script_pub_key, 'redeemScript': redeem_script, 'witnessScript': witness_script, 'amount': 10}])
+ # Check the signing completed successfully
+ assert 'complete' in spending_tx_signed
+ assert_equal(spending_tx_signed['complete'], True)
+ self.nodes[0].sendrawtransaction(spending_tx_signed['hex'])
+
+ def run_test(self):
+ self.successful_signing_test()
+ self.witness_script_test()
+
+
+if __name__ == '__main__':
+ SignRawTransactionWithKeyTest().main()
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index 40fcbf7761..574ea10356 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -162,30 +162,6 @@ def create_tx_with_script(prevtx, n, script_sig=b"", *, amount, script_pub_key=C
tx.calc_sha256()
return tx
-def create_transaction(node, txid, to_address, *, amount):
- """ Return signed transaction spending the first output of the
- input txid. Note that the node must have a wallet that can
- sign for the output that is being spent.
- """
- raw_tx = create_raw_transaction(node, txid, to_address, amount=amount)
- tx = tx_from_hex(raw_tx)
- return tx
-
-def create_raw_transaction(node, txid, to_address, *, amount):
- """ Return raw signed transaction spending the first output of the
- input txid. Note that the node must have a wallet that can sign
- for the output that is being spent.
- """
- psbt = node.createpsbt(inputs=[{"txid": txid, "vout": 0}], outputs={to_address: amount})
- for _ in range(2):
- for w in node.listwallets():
- wrpc = node.get_wallet_rpc(w)
- signed_psbt = wrpc.walletprocesspsbt(psbt)
- psbt = signed_psbt['psbt']
- final_psbt = node.finalizepsbt(psbt)
- assert_equal(final_psbt["complete"], True)
- return final_psbt['hex']
-
def get_legacy_sigopcount_block(block, accurate=True):
count = 0
for tx in block.vtx:
diff --git a/test/functional/test_framework/key.py b/test/functional/test_framework/key.py
index e5dea66963..68afc1383d 100644
--- a/test/functional/test_framework/key.py
+++ b/test/functional/test_framework/key.py
@@ -15,6 +15,10 @@ import unittest
from .util import modinv
+# Point with no known discrete log.
+H_POINT = "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0"
+
+
def TaggedHash(tag, data):
ss = hashlib.sha256(tag.encode('utf-8')).digest()
ss += ss
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index aae44c0ac0..8a928a1e50 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -39,7 +39,7 @@ MAX_BLOOM_HASH_FUNCS = 50
COIN = 100000000 # 1 btc in satoshis
MAX_MONEY = 21000000 * COIN
-BIP125_SEQUENCE_NUMBER = 0xfffffffd # Sequence number that is rbf-opt-in (BIP 125) and csv-opt-out (BIP 68)
+MAX_BIP125_RBF_SEQUENCE = 0xfffffffd # Sequence number that is rbf-opt-in (BIP 125) and csv-opt-out (BIP 68)
SEQUENCE_FINAL = 0xffffffff # Sequence number that disables nLockTime if set for every input of a tx
MAX_PROTOCOL_MESSAGE_LENGTH = 4000000 # Maximum length of incoming protocol messages
@@ -65,6 +65,13 @@ FILTER_TYPE_BASIC = 0
WITNESS_SCALE_FACTOR = 4
+DEFAULT_ANCESTOR_LIMIT = 25 # default max number of in-mempool ancestors
+DEFAULT_DESCENDANT_LIMIT = 25 # default max number of in-mempool descendants
+
+# Default setting for -datacarriersize. 80 bytes of data, +1 for OP_RETURN, +2 for the pushdata opcodes.
+MAX_OP_RETURN_RELAY = 83
+
+DEFAULT_MEMPOOL_EXPIRY_HOURS = 336 # hours
def sha256(s):
return hashlib.sha256(s).digest()
@@ -208,6 +215,20 @@ def tx_from_hex(hex_string):
return from_hex(CTransaction(), hex_string)
+# like from_hex, but without the hex part
+def from_binary(cls, stream):
+ """deserialize a binary stream (or bytes object) into an object"""
+ # handle bytes object by turning it into a stream
+ was_bytes = isinstance(stream, bytes)
+ if was_bytes:
+ stream = BytesIO(stream)
+ obj = cls()
+ obj.deserialize(stream)
+ if was_bytes:
+ assert len(stream.read()) == 0
+ return obj
+
+
# Objects that map to bitcoind objects, which can be serialized/deserialized
diff --git a/test/functional/test_framework/psbt.py b/test/functional/test_framework/psbt.py
new file mode 100644
index 0000000000..3a5b4ec74d
--- /dev/null
+++ b/test/functional/test_framework/psbt.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import base64
+
+from .messages import (
+ CTransaction,
+ deser_string,
+ from_binary,
+ ser_compact_size,
+)
+
+
+# global types
+PSBT_GLOBAL_UNSIGNED_TX = 0x00
+PSBT_GLOBAL_XPUB = 0x01
+PSBT_GLOBAL_TX_VERSION = 0x02
+PSBT_GLOBAL_FALLBACK_LOCKTIME = 0x03
+PSBT_GLOBAL_INPUT_COUNT = 0x04
+PSBT_GLOBAL_OUTPUT_COUNT = 0x05
+PSBT_GLOBAL_TX_MODIFIABLE = 0x06
+PSBT_GLOBAL_VERSION = 0xfb
+PSBT_GLOBAL_PROPRIETARY = 0xfc
+
+# per-input types
+PSBT_IN_NON_WITNESS_UTXO = 0x00
+PSBT_IN_WITNESS_UTXO = 0x01
+PSBT_IN_PARTIAL_SIG = 0x02
+PSBT_IN_SIGHASH_TYPE = 0x03
+PSBT_IN_REDEEM_SCRIPT = 0x04
+PSBT_IN_WITNESS_SCRIPT = 0x05
+PSBT_IN_BIP32_DERIVATION = 0x06
+PSBT_IN_FINAL_SCRIPTSIG = 0x07
+PSBT_IN_FINAL_SCRIPTWITNESS = 0x08
+PSBT_IN_POR_COMMITMENT = 0x09
+PSBT_IN_RIPEMD160 = 0x0a
+PSBT_IN_SHA256 = 0x0b
+PSBT_IN_HASH160 = 0x0c
+PSBT_IN_HASH256 = 0x0d
+PSBT_IN_PREVIOUS_TXID = 0x0e
+PSBT_IN_OUTPUT_INDEX = 0x0f
+PSBT_IN_SEQUENCE = 0x10
+PSBT_IN_REQUIRED_TIME_LOCKTIME = 0x11
+PSBT_IN_REQUIRED_HEIGHT_LOCKTIME = 0x12
+PSBT_IN_TAP_KEY_SIG = 0x13
+PSBT_IN_TAP_SCRIPT_SIG = 0x14
+PSBT_IN_TAP_LEAF_SCRIPT = 0x15
+PSBT_IN_TAP_BIP32_DERIVATION = 0x16
+PSBT_IN_TAP_INTERNAL_KEY = 0x17
+PSBT_IN_TAP_MERKLE_ROOT = 0x18
+PSBT_IN_PROPRIETARY = 0xfc
+
+# per-output types
+PSBT_OUT_REDEEM_SCRIPT = 0x00
+PSBT_OUT_WITNESS_SCRIPT = 0x01
+PSBT_OUT_BIP32_DERIVATION = 0x02
+PSBT_OUT_AMOUNT = 0x03
+PSBT_OUT_SCRIPT = 0x04
+PSBT_OUT_TAP_INTERNAL_KEY = 0x05
+PSBT_OUT_TAP_TREE = 0x06
+PSBT_OUT_TAP_BIP32_DERIVATION = 0x07
+PSBT_OUT_PROPRIETARY = 0xfc
+
+
+class PSBTMap:
+ """Class for serializing and deserializing PSBT maps"""
+
+ def __init__(self, map=None):
+ self.map = map if map is not None else {}
+
+ def deserialize(self, f):
+ m = {}
+ while True:
+ k = deser_string(f)
+ if len(k) == 0:
+ break
+ v = deser_string(f)
+ if len(k) == 1:
+ k = k[0]
+ assert k not in m
+ m[k] = v
+ self.map = m
+
+ def serialize(self):
+ m = b""
+ for k,v in self.map.items():
+ if isinstance(k, int) and 0 <= k and k <= 255:
+ k = bytes([k])
+ m += ser_compact_size(len(k)) + k
+ m += ser_compact_size(len(v)) + v
+ m += b"\x00"
+ return m
+
+class PSBT:
+ """Class for serializing and deserializing PSBTs"""
+
+ def __init__(self, *, g=None, i=None, o=None):
+ self.g = g if g is not None else PSBTMap()
+ self.i = i if i is not None else []
+ self.o = o if o is not None else []
+ self.tx = None
+
+ def deserialize(self, f):
+ assert f.read(5) == b"psbt\xff"
+ self.g = from_binary(PSBTMap, f)
+ assert 0 in self.g.map
+ self.tx = from_binary(CTransaction, self.g.map[0])
+ self.i = [from_binary(PSBTMap, f) for _ in self.tx.vin]
+ self.o = [from_binary(PSBTMap, f) for _ in self.tx.vout]
+ return self
+
+ def serialize(self):
+ assert isinstance(self.g, PSBTMap)
+ assert isinstance(self.i, list) and all(isinstance(x, PSBTMap) for x in self.i)
+ assert isinstance(self.o, list) and all(isinstance(x, PSBTMap) for x in self.o)
+ assert 0 in self.g.map
+ tx = from_binary(CTransaction, self.g.map[0])
+ assert len(tx.vin) == len(self.i)
+ assert len(tx.vout) == len(self.o)
+
+ psbt = [x.serialize() for x in [self.g] + self.i + self.o]
+ return b"psbt\xff" + b"".join(psbt)
+
+ def make_blank(self):
+ """
+ Remove all fields except for PSBT_GLOBAL_UNSIGNED_TX
+ """
+ for m in self.i + self.o:
+ m.map.clear()
+
+ self.g = PSBTMap(map={0: self.g.map[0]})
+
+ def to_base64(self):
+ return base64.b64encode(self.serialize()).decode("utf8")
+
+ @classmethod
+ def from_base64(cls, b64psbt):
+ return from_binary(cls, base64.b64decode(b64psbt))
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 3f02d21d42..b1164b98fd 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -581,6 +581,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
def connect_nodes(self, a, b):
from_connection = self.nodes[a]
to_connection = self.nodes[b]
+ from_num_peers = 1 + len(from_connection.getpeerinfo())
+ to_num_peers = 1 + len(to_connection.getpeerinfo())
ip_port = "127.0.0.1:" + str(p2p_port(b))
from_connection.addnode(ip_port, "onetry")
# poll until version handshake complete to avoid race conditions
@@ -588,30 +590,30 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# See comments in net_processing:
# * Must have a version message before anything else
# * Must have a verack message before anything else
- wait_until_helper(lambda: all(peer['version'] != 0 for peer in from_connection.getpeerinfo()))
- wait_until_helper(lambda: all(peer['version'] != 0 for peer in to_connection.getpeerinfo()))
- wait_until_helper(lambda: all(peer['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in from_connection.getpeerinfo()))
- wait_until_helper(lambda: all(peer['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in to_connection.getpeerinfo()))
+ self.wait_until(lambda: sum(peer['version'] != 0 for peer in from_connection.getpeerinfo()) == from_num_peers)
+ self.wait_until(lambda: sum(peer['version'] != 0 for peer in to_connection.getpeerinfo()) == to_num_peers)
+ self.wait_until(lambda: sum(peer['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in from_connection.getpeerinfo()) == from_num_peers)
+ self.wait_until(lambda: sum(peer['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in to_connection.getpeerinfo()) == to_num_peers)
def disconnect_nodes(self, a, b):
- def disconnect_nodes_helper(from_connection, node_num):
- def get_peer_ids():
+ def disconnect_nodes_helper(node_a, node_b):
+ def get_peer_ids(from_connection, node_num):
result = []
for peer in from_connection.getpeerinfo():
if "testnode{}".format(node_num) in peer['subver']:
result.append(peer['id'])
return result
- peer_ids = get_peer_ids()
+ peer_ids = get_peer_ids(node_a, node_b.index)
if not peer_ids:
self.log.warning("disconnect_nodes: {} and {} were not connected".format(
- from_connection.index,
- node_num,
+ node_a.index,
+ node_b.index,
))
return
for peer_id in peer_ids:
try:
- from_connection.disconnectnode(nodeid=peer_id)
+ node_a.disconnectnode(nodeid=peer_id)
except JSONRPCException as e:
# If this node is disconnected between calculating the peer id
# and issuing the disconnect, don't worry about it.
@@ -620,9 +622,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
raise
# wait to disconnect
- wait_until_helper(lambda: not get_peer_ids(), timeout=5)
+ self.wait_until(lambda: not get_peer_ids(node_a, node_b.index), timeout=5)
+ self.wait_until(lambda: not get_peer_ids(node_b, node_a.index), timeout=5)
- disconnect_nodes_helper(self.nodes[a], b)
+ disconnect_nodes_helper(self.nodes[a], self.nodes[b])
def split_network(self):
"""
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 03f6c8adea..e35cae006f 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -118,6 +118,8 @@ class TestNode():
self.args.append("-logthreadnames")
if self.version_is_at_least(219900):
self.args.append("-logsourcelocations")
+ if self.version_is_at_least(239000):
+ self.args.append("-loglevel=trace")
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
self.use_cli = use_cli
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 6a588275ea..bfc835f272 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -12,6 +12,7 @@ import inspect
import json
import logging
import os
+import random
import re
import time
import unittest
@@ -28,6 +29,10 @@ logger = logging.getLogger("TestFramework.utils")
def assert_approx(v, vexp, vspan=0.00001):
"""Assert that `v` is within `vspan` of `vexp`"""
+ if isinstance(v, Decimal) or isinstance(vexp, Decimal):
+ v=Decimal(v)
+ vexp=Decimal(vexp)
+ vspan=Decimal(vspan)
if v < vexp - vspan:
raise AssertionError("%s < [%s..%s]" % (str(v), str(vexp - vspan), str(vexp + vspan)))
if v > vexp + vspan:
@@ -286,6 +291,13 @@ def sha256sum_file(filename):
d = f.read(4096)
return h.digest()
+
+# TODO: Remove and use random.randbytes(n) instead, available in Python 3.9
+def random_bytes(n):
+ """Return a random bytes object of length n."""
+ return bytes(random.getrandbits(8) for i in range(n))
+
+
# RPC/P2P connection constants and functions
############################################
@@ -499,38 +511,26 @@ def chain_transaction(node, parent_txids, vouts, value, fee, num_outputs):
# Create large OP_RETURN txouts that can be appended to a transaction
-# to make it large (helper for constructing large transactions).
+# to make it large (helper for constructing large transactions). The
+# total serialized size of the txouts is about 66k vbytes.
def gen_return_txouts():
- # Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
- # So we have big transactions (and therefore can't fit very many into each block)
- # create one script_pubkey
- script_pubkey = "6a4d0200" # OP_RETURN OP_PUSH2 512 bytes
- for _ in range(512):
- script_pubkey = script_pubkey + "01"
- # concatenate 128 txouts of above script_pubkey which we'll insert before the txout for change
- txouts = []
from .messages import CTxOut
- txout = CTxOut()
- txout.nValue = 0
- txout.scriptPubKey = bytes.fromhex(script_pubkey)
- for _ in range(128):
- txouts.append(txout)
+ from .script import CScript, OP_RETURN
+ txouts = [CTxOut(nValue=0, scriptPubKey=CScript([OP_RETURN, b'\x01'*67437]))]
+ assert_equal(sum([len(txout.serialize()) for txout in txouts]), 67456)
return txouts
# Create a spend of each passed-in utxo, splicing in "txouts" to each raw
# transaction to make it large. See gen_return_txouts() above.
def create_lots_of_big_transactions(mini_wallet, node, fee, tx_batch_size, txouts, utxos=None):
- from .messages import COIN
- fee_sats = int(fee * COIN)
txids = []
use_internal_utxos = utxos is None
for _ in range(tx_batch_size):
tx = mini_wallet.create_self_transfer(
utxo_to_spend=None if use_internal_utxos else utxos.pop(),
- fee_rate=0,
+ fee=fee,
)["tx"]
- tx.vout[0].nValue -= fee_sats
tx.vout.extend(txouts)
res = node.testmempoolaccept([tx.serialize().hex()])[0]
assert_equal(res['fees']['base'], fee)
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index 1e154fbd44..374fda5c23 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -7,7 +7,6 @@
from copy import deepcopy
from decimal import Decimal
from enum import Enum
-from random import choice
from typing import (
Any,
List,
@@ -40,6 +39,7 @@ from test_framework.script import (
LegacySignatureHash,
LEAF_VERSION_TAPSCRIPT,
OP_NOP,
+ OP_RETURN,
OP_TRUE,
SIGHASH_ALL,
taproot_construct,
@@ -101,6 +101,21 @@ class MiniWallet:
self._address, self._internal_key = create_deterministic_address_bcrt1_p2tr_op_true()
self._scriptPubKey = bytes.fromhex(self._test_node.validateaddress(self._address)['scriptPubKey'])
+ def _create_utxo(self, *, txid, vout, value, height):
+ return {"txid": txid, "vout": vout, "value": value, "height": height}
+
+ def _bulk_tx(self, tx, target_weight):
+ """Pad a transaction with extra outputs until it reaches a target weight (or higher).
+ returns the tx
+ """
+ tx.vout.append(CTxOut(nValue=0, scriptPubKey=CScript([OP_RETURN, b'a'])))
+ dummy_vbytes = (target_weight - tx.get_weight() + 3) // 4
+ tx.vout[-1].scriptPubKey = CScript([OP_RETURN, b'a' * dummy_vbytes])
+ # Lower bound should always be off by at most 3
+ assert_greater_than_or_equal(tx.get_weight(), target_weight)
+ # Higher bound should always be off by at most 3 + 12 weight (for encoding the length)
+ assert_greater_than_or_equal(target_weight + 15, tx.get_weight())
+
def get_balance(self):
return sum(u['value'] for u in self._utxos)
@@ -110,13 +125,22 @@ class MiniWallet:
res = self._test_node.scantxoutset(action="start", scanobjects=[self.get_descriptor()])
assert_equal(True, res['success'])
for utxo in res['unspents']:
- self._utxos.append({'txid': utxo['txid'], 'vout': utxo['vout'], 'value': utxo['amount'], 'height': utxo['height']})
+ self._utxos.append(self._create_utxo(txid=utxo["txid"], vout=utxo["vout"], value=utxo["amount"], height=utxo["height"]))
def scan_tx(self, tx):
- """Scan the tx for self._scriptPubKey outputs and add them to self._utxos"""
+ """Scan the tx and adjust the internal list of owned utxos"""
+ for spent in tx["vin"]:
+ # Mark spent. This may happen when the caller has ownership of a
+ # utxo that remained in this wallet. For example, by passing
+ # mark_as_spent=False to get_utxo or by using an utxo returned by a
+ # create_self_transfer* call.
+ try:
+ self.get_utxo(txid=spent["txid"], vout=spent["vout"])
+ except StopIteration:
+ pass
for out in tx['vout']:
if out['scriptPubKey']['hex'] == self._scriptPubKey.hex():
- self._utxos.append({'txid': tx['txid'], 'vout': out['n'], 'value': out['value'], 'height': 0})
+ self._utxos.append(self._create_utxo(txid=tx["txid"], vout=out["n"], value=out["value"], height=0))
def sign_tx(self, tx, fixed_length=True):
"""Sign tx that has been created by MiniWallet in P2PK mode"""
@@ -135,12 +159,16 @@ class MiniWallet:
tx.rehash()
def generate(self, num_blocks, **kwargs):
- """Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list"""
+ """Generate blocks with coinbase outputs to the internal address, and call rescan_utxos"""
blocks = self._test_node.generatetodescriptor(num_blocks, self.get_descriptor(), **kwargs)
- for b in blocks:
- block_info = self._test_node.getblock(blockhash=b, verbosity=2)
- cb_tx = block_info['tx'][0]
- self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value'], 'height': block_info['height']})
+ # Calling rescan_utxos here makes sure that after a generate the utxo
+ # set is in a clean state. For example, the wallet will update
+ # - if the caller consumed utxos, but never used them
+ # - if the caller sent a transaction that is not mined or got rbf'd
+ # - after block re-orgs
+ # - the utxo height for mined mempool txs
+ # - However, the wallet will not consider remaining mempool txs
+ self.rescan_utxos()
return blocks
def get_scriptPubKey(self):
@@ -181,7 +209,7 @@ class MiniWallet:
return utxos
def send_self_transfer(self, *, from_node, **kwargs):
- """Create and send a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed."""
+ """Call create_self_transfer and send the transaction."""
tx = self.create_self_transfer(**kwargs)
self.sendrawtransaction(from_node=from_node, tx_hex=tx['hex'])
return tx
@@ -206,41 +234,38 @@ class MiniWallet:
return txid, 1
def send_self_transfer_multi(self, *, from_node, **kwargs):
- """
- Create and send a transaction that spends the given UTXOs and creates a
- certain number of outputs with equal amounts.
-
- Returns a dictionary with
- - txid
- - serialized transaction in hex format
- - transaction as CTransaction instance
- - list of newly created UTXOs, ordered by vout index
- """
+ """Call create_self_transfer_multi and send the transaction."""
tx = self.create_self_transfer_multi(**kwargs)
- txid = self.sendrawtransaction(from_node=from_node, tx_hex=tx.serialize().hex())
- return {'new_utxos': [self.get_utxo(txid=txid, vout=vout) for vout in range(len(tx.vout))],
- 'txid': txid, 'hex': tx.serialize().hex(), 'tx': tx}
+ self.sendrawtransaction(from_node=from_node, tx_hex=tx["hex"])
+ return tx
def create_self_transfer_multi(
self,
*,
utxos_to_spend: Optional[List[dict]] = None,
num_outputs=1,
+ amount_per_output=0,
sequence=0,
fee_per_output=1000,
+ target_weight=0
):
"""
Create and return a transaction that spends the given UTXOs and creates a
- certain number of outputs with equal amounts.
+ certain number of outputs with equal amounts. The output amounts can be
+ set by amount_per_output or automatically calculated with a fee_per_output.
"""
utxos_to_spend = utxos_to_spend or [self.get_utxo()]
+ sequence = [sequence] * len(utxos_to_spend) if type(sequence) is int else sequence
+ assert_equal(len(utxos_to_spend), len(sequence))
# create simple tx template (1 input, 1 output)
tx = self.create_self_transfer(
fee_rate=0,
- utxo_to_spend=utxos_to_spend[0], sequence=sequence)["tx"]
+ utxo_to_spend=utxos_to_spend[0])["tx"]
# duplicate inputs, witnesses and outputs
tx.vin = [deepcopy(tx.vin[0]) for _ in range(len(utxos_to_spend))]
+ for txin, seq in zip(tx.vin, sequence):
+ txin.nSequence = seq
tx.wit.vtxinwit = [deepcopy(tx.wit.vtxinwit[0]) for _ in range(len(utxos_to_spend))]
tx.vout = [deepcopy(tx.vout[0]) for _ in range(num_outputs)]
@@ -252,24 +277,41 @@ class MiniWallet:
inputs_value_total = sum([int(COIN * utxo['value']) for utxo in utxos_to_spend])
outputs_value_total = inputs_value_total - fee_per_output * num_outputs
for o in tx.vout:
- o.nValue = outputs_value_total // num_outputs
- return tx
+ o.nValue = amount_per_output or (outputs_value_total // num_outputs)
- def create_self_transfer(self, *, fee_rate=Decimal("0.003"), utxo_to_spend=None, locktime=0, sequence=0):
- """Create and return a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed."""
+ if target_weight:
+ self._bulk_tx(tx, target_weight)
+
+ txid = tx.rehash()
+ return {
+ "new_utxos": [self._create_utxo(
+ txid=txid,
+ vout=i,
+ value=Decimal(tx.vout[i].nValue) / COIN,
+ height=0,
+ ) for i in range(len(tx.vout))],
+ "txid": txid,
+ "hex": tx.serialize().hex(),
+ "tx": tx,
+ }
+
+ def create_self_transfer(self, *, fee_rate=Decimal("0.003"), fee=Decimal("0"), utxo_to_spend=None, locktime=0, sequence=0, target_weight=0):
+ """Create and return a tx with the specified fee. If fee is 0, use fee_rate, where the resulting fee may be exact or at most one satoshi higher than needed."""
utxo_to_spend = utxo_to_spend or self.get_utxo()
+ assert fee_rate >= 0
+ assert fee >= 0
if self._mode in (MiniWalletMode.RAW_OP_TRUE, MiniWalletMode.ADDRESS_OP_TRUE):
vsize = Decimal(104) # anyone-can-spend
elif self._mode == MiniWalletMode.RAW_P2PK:
vsize = Decimal(168) # P2PK (73 bytes scriptSig + 35 bytes scriptPubKey + 60 bytes other)
else:
assert False
- send_value = int(COIN * (utxo_to_spend['value'] - fee_rate * (vsize / 1000)))
+ send_value = utxo_to_spend["value"] - (fee or (fee_rate * vsize / 1000))
assert send_value > 0
tx = CTransaction()
tx.vin = [CTxIn(COutPoint(int(utxo_to_spend['txid'], 16), utxo_to_spend['vout']), nSequence=sequence)]
- tx.vout = [CTxOut(send_value, self._scriptPubKey)]
+ tx.vout = [CTxOut(int(COIN * send_value), bytearray(self._scriptPubKey))]
tx.nLockTime = locktime
if self._mode == MiniWalletMode.RAW_P2PK:
self.sign_tx(tx)
@@ -280,17 +322,33 @@ class MiniWallet:
tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE]), bytes([LEAF_VERSION_TAPSCRIPT]) + self._internal_key]
else:
assert False
- tx_hex = tx.serialize().hex()
assert_equal(tx.get_vsize(), vsize)
- return {'txid': tx.rehash(), 'wtxid': tx.getwtxid(), 'hex': tx_hex, 'tx': tx}
+ if target_weight:
+ self._bulk_tx(tx, target_weight)
+
+ tx_hex = tx.serialize().hex()
+ new_utxo = self._create_utxo(txid=tx.rehash(), vout=0, value=send_value, height=0)
+
+ return {"txid": new_utxo["txid"], "wtxid": tx.getwtxid(), "hex": tx_hex, "tx": tx, "new_utxo": new_utxo}
def sendrawtransaction(self, *, from_node, tx_hex, maxfeerate=0, **kwargs):
txid = from_node.sendrawtransaction(hexstring=tx_hex, maxfeerate=maxfeerate, **kwargs)
self.scan_tx(from_node.decoderawtransaction(tx_hex))
return txid
+ def send_self_transfer_chain(self, *, from_node, chain_length, utxo_to_spend=None):
+ """Create and send a "chain" of chain_length transactions. The nth transaction in
+ the chain is a child of the n-1th transaction and parent of the n+1th transaction.
+
+ Returns the chaintip (nth) utxo
+ """
+ chaintip_utxo = utxo_to_spend or self.get_utxo()
+ for _ in range(chain_length):
+ chaintip_utxo = self.send_self_transfer(utxo_to_spend=chaintip_utxo, from_node=from_node)["new_utxo"]
+ return chaintip_utxo
+
def getnewdestination(address_type='bech32m'):
"""Generate a random destination of the specified type and return the
@@ -383,23 +441,3 @@ def create_raw_chain(node, first_coin, address, privkeys, chain_length=25):
chain_txns.append(tx)
return (chain_hex, chain_txns)
-
-def bulk_transaction(tx, node, target_weight, privkeys, prevtxs=None):
- """Pad a transaction with extra outputs until it reaches a target weight (or higher).
- returns CTransaction object
- """
- tx_heavy = deepcopy(tx)
- assert_greater_than_or_equal(target_weight, tx_heavy.get_weight())
- while tx_heavy.get_weight() < target_weight:
- random_spk = "6a4d0200" # OP_RETURN OP_PUSH2 512 bytes
- for _ in range(512*2):
- random_spk += choice("0123456789ABCDEF")
- tx_heavy.vout.append(CTxOut(0, bytes.fromhex(random_spk)))
- # Re-sign the transaction
- if privkeys:
- signed = node.signrawtransactionwithkey(tx_heavy.serialize().hex(), privkeys, prevtxs)
- return tx_from_hex(signed["hex"])
- # OP_TRUE
- tx_heavy.wit.vtxinwit = [CTxInWitness()]
- tx_heavy.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
- return tx_heavy
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 6a44f9d21d..caa4af957a 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -130,6 +130,7 @@ BASE_SCRIPTS = [
'wallet_address_types.py --descriptors',
'feature_bip68_sequence.py',
'p2p_feefilter.py',
+ 'rpc_packages.py',
'feature_reindex.py',
'feature_abortnode.py',
# vv Tests less than 30s vv
@@ -155,6 +156,7 @@ BASE_SCRIPTS = [
'mempool_spend_coinbase.py',
'wallet_avoidreuse.py --legacy-wallet',
'wallet_avoidreuse.py --descriptors',
+ 'wallet_avoid_mixing_output_types.py --descriptors',
'mempool_reorg.py',
'mempool_persist.py',
'p2p_block_sync.py',
@@ -181,8 +183,10 @@ BASE_SCRIPTS = [
'rpc_whitelist.py',
'feature_proxy.py',
'feature_syscall_sandbox.py',
- 'rpc_signrawtransaction.py --legacy-wallet',
- 'rpc_signrawtransaction.py --descriptors',
+ 'wallet_signrawtransactionwithwallet.py --legacy-wallet',
+ 'wallet_signrawtransactionwithwallet.py --descriptors',
+ 'rpc_signrawtransactionwithkey.py',
+ 'p2p_headers_sync_with_minchainwork.py',
'rpc_rawtransaction.py --legacy-wallet',
'wallet_groups.py --legacy-wallet',
'wallet_transactiontime_rescan.py --descriptors',
@@ -203,6 +207,7 @@ BASE_SCRIPTS = [
'wallet_keypool.py --legacy-wallet',
'wallet_keypool.py --descriptors',
'wallet_descriptor.py --descriptors',
+ 'wallet_miniscript.py',
'feature_maxtipage.py',
'p2p_nobloomfilter_messages.py',
'p2p_filter.py',
@@ -226,12 +231,10 @@ BASE_SCRIPTS = [
'rpc_getblockfrompeer.py',
'rpc_invalidateblock.py',
'feature_utxo_set_hash.py',
- 'feature_rbf.py --legacy-wallet',
- 'feature_rbf.py --descriptors',
+ 'feature_rbf.py',
'mempool_packages.py',
'mempool_package_onemore.py',
'rpc_createmultisig.py',
- 'rpc_packages.py',
'mempool_package_limits.py',
'feature_versionbits_warning.py',
'rpc_preciousblock.py',
@@ -244,8 +247,8 @@ BASE_SCRIPTS = [
'rpc_generate.py',
'wallet_balance.py --legacy-wallet',
'wallet_balance.py --descriptors',
- 'feature_nulldummy.py --legacy-wallet',
- 'feature_nulldummy.py --descriptors',
+ 'p2p_initial_headers_sync.py',
+ 'feature_nulldummy.py',
'mempool_accept.py',
'mempool_expiry.py',
'wallet_import_rescan.py --legacy-wallet',
@@ -263,6 +266,8 @@ BASE_SCRIPTS = [
'wallet_implicitsegwit.py --legacy-wallet',
'rpc_named_arguments.py',
'feature_startupnotify.py',
+ 'wallet_simulaterawtx.py --legacy-wallet',
+ 'wallet_simulaterawtx.py --descriptors',
'wallet_listsinceblock.py --legacy-wallet',
'wallet_listsinceblock.py --descriptors',
'wallet_listdescriptors.py --descriptors',
@@ -311,11 +316,13 @@ BASE_SCRIPTS = [
'rpc_deriveaddresses.py',
'rpc_deriveaddresses.py --usecli',
'p2p_ping.py',
+ 'p2p_tx_privacy.py',
'rpc_scantxoutset.py',
'feature_txindex_compatibility.py',
'feature_unsupported_utxo_db.py',
'feature_logging.py',
'feature_anchors.py',
+ 'mempool_datacarrier.py',
'feature_coinstatsindex.py',
'wallet_orphanedreward.py',
'wallet_timelock.py',
@@ -324,6 +331,7 @@ BASE_SCRIPTS = [
'feature_blocksdir.py',
'wallet_startup.py',
'p2p_i2p_ports.py',
+ 'p2p_i2p_sessions.py',
'feature_config_args.py',
'feature_presegwit_node_upgrade.py',
'feature_settings.py',
@@ -333,6 +341,7 @@ BASE_SCRIPTS = [
'feature_dirsymlinks.py',
'feature_help.py',
'feature_shutdown.py',
+ 'wallet_migration.py',
'p2p_ibd_txrelay.py',
# Don't append tests at the end to avoid merge conflicts
# Put them in a random line within the section that fits their approximate run-time
@@ -546,14 +555,14 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=
while i < test_count:
if failfast and not all_passed:
break
- for test_result, testdir, stdout, stderr in job_queue.get_next():
+ for test_result, testdir, stdout, stderr, skip_reason in job_queue.get_next():
test_results.append(test_result)
i += 1
done_str = "{}/{} - {}{}{}".format(i, test_count, BOLD[1], test_result.name, BOLD[0])
if test_result.status == "Passed":
logging.debug("%s passed, Duration: %s s" % (done_str, test_result.time))
elif test_result.status == "Skipped":
- logging.debug("%s skipped" % (done_str))
+ logging.debug(f"{done_str} skipped ({skip_reason})")
else:
all_passed = False
print("%s failed, Duration: %s s\n" % (done_str, test_result.time))
@@ -677,10 +686,12 @@ class TestHandler:
log_out.seek(0), log_err.seek(0)
[stdout, stderr] = [log_file.read().decode('utf-8') for log_file in (log_out, log_err)]
log_out.close(), log_err.close()
+ skip_reason = None
if proc.returncode == TEST_EXIT_PASSED and stderr == "":
status = "Passed"
elif proc.returncode == TEST_EXIT_SKIPPED:
status = "Skipped"
+ skip_reason = re.search(r"Test Skipped: (.*)", stdout).group(1)
else:
status = "Failed"
self.num_running -= 1
@@ -689,7 +700,7 @@ class TestHandler:
clearline = '\r' + (' ' * dot_count) + '\r'
print(clearline, end='', flush=True)
dot_count = 0
- ret.append((TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr))
+ ret.append((TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr, skip_reason))
if ret:
return ret
if self.use_term_control:
diff --git a/test/functional/tool_wallet.py b/test/functional/tool_wallet.py
index 2cb9dc4523..1e5ce513cb 100755
--- a/test/functional/tool_wallet.py
+++ b/test/functional/tool_wallet.py
@@ -68,7 +68,7 @@ class ToolWalletTest(BitcoinTestFramework):
result = 'unchanged' if new == old else 'increased!'
self.log.debug('Wallet file timestamp {}'.format(result))
- def get_expected_info_output(self, name="", transactions=0, keypool=2, address=0):
+ def get_expected_info_output(self, name="", transactions=0, keypool=2, address=0, imported_privs=0):
wallet_name = self.default_wallet_name if name == "" else name
if self.options.descriptors:
output_types = 4 # p2pkh, p2sh, segwit, bech32m
@@ -83,7 +83,7 @@ class ToolWalletTest(BitcoinTestFramework):
Keypool Size: %d
Transactions: %d
Address Book: %d
- ''' % (wallet_name, keypool * output_types, transactions, address))
+ ''' % (wallet_name, keypool * output_types, transactions, imported_privs * 3 + address))
else:
output_types = 3 # p2pkh, p2sh, segwit. Legacy wallets do not support bech32m.
return textwrap.dedent('''\
@@ -97,7 +97,7 @@ class ToolWalletTest(BitcoinTestFramework):
Keypool Size: %d
Transactions: %d
Address Book: %d
- ''' % (wallet_name, keypool, transactions, address * output_types))
+ ''' % (wallet_name, keypool, transactions, (address + imported_privs) * output_types))
def read_dump(self, filename):
dump = OrderedDict()
@@ -219,7 +219,7 @@ class ToolWalletTest(BitcoinTestFramework):
# shasum_before = self.wallet_shasum()
timestamp_before = self.wallet_timestamp()
self.log.debug('Wallet file timestamp before calling info: {}'.format(timestamp_before))
- out = self.get_expected_info_output(address=1)
+ out = self.get_expected_info_output(imported_privs=1)
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info')
timestamp_after = self.wallet_timestamp()
self.log.debug('Wallet file timestamp after calling info: {}'.format(timestamp_after))
@@ -250,7 +250,7 @@ class ToolWalletTest(BitcoinTestFramework):
shasum_before = self.wallet_shasum()
timestamp_before = self.wallet_timestamp()
self.log.debug('Wallet file timestamp before calling info: {}'.format(timestamp_before))
- out = self.get_expected_info_output(transactions=1, address=1)
+ out = self.get_expected_info_output(transactions=1, imported_privs=1)
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info')
shasum_after = self.wallet_shasum()
timestamp_after = self.wallet_timestamp()
diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py
index 36fcdb36d6..d7850b41ac 100755
--- a/test/functional/wallet_abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -24,6 +24,9 @@ class AbandonConflictTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.extra_args = [["-minrelaytxfee=0.00001"], []]
+ # whitelist peers to speed up tx relay / mempool sync
+ for args in self.extra_args:
+ args.append("-whitelist=noban@127.0.0.1")
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index f7c80f805c..5b836f693f 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -345,31 +345,19 @@ class AddressTypeTest(BitcoinTestFramework):
self.log.info("Nodes with addresstype=legacy never use a P2WPKH change output (unless changetype is set otherwise):")
self.test_change_output_type(0, [to_address_bech32_1], 'legacy')
- if self.options.descriptors:
- self.log.info("Nodes with addresstype=p2sh-segwit match the change output")
- self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit')
- self.test_change_output_type(1, [to_address_bech32_1], 'bech32')
- self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32')
- self.test_change_output_type(1, [to_address_bech32_1, to_address_bech32_2], 'bech32')
- else:
- self.log.info("Nodes with addresstype=p2sh-segwit match the change output")
- self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit')
- self.test_change_output_type(1, [to_address_bech32_1], 'bech32')
- self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32')
- self.test_change_output_type(1, [to_address_bech32_1, to_address_bech32_2], 'bech32')
+ self.log.info("Nodes with addresstype=p2sh-segwit match the change output")
+ self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit')
+ self.test_change_output_type(1, [to_address_bech32_1], 'bech32')
+ self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32')
+ self.test_change_output_type(1, [to_address_bech32_1, to_address_bech32_2], 'bech32')
self.log.info("Nodes with change_type=bech32 always use a P2WPKH change output:")
self.test_change_output_type(2, [to_address_bech32_1], 'bech32')
self.test_change_output_type(2, [to_address_p2sh], 'bech32')
- if self.options.descriptors:
- self.log.info("Nodes with addresstype=bech32 match the change output (unless changetype is set otherwise):")
- self.test_change_output_type(3, [to_address_bech32_1], 'bech32')
- self.test_change_output_type(3, [to_address_p2sh], 'p2sh-segwit')
- else:
- self.log.info("Nodes with addresstype=bech32 match the change output (unless changetype is set otherwise):")
- self.test_change_output_type(3, [to_address_bech32_1], 'bech32')
- self.test_change_output_type(3, [to_address_p2sh], 'p2sh-segwit')
+ self.log.info("Nodes with addresstype=bech32 match the change output (unless changetype is set otherwise):")
+ self.test_change_output_type(3, [to_address_bech32_1], 'bech32')
+ self.test_change_output_type(3, [to_address_p2sh], 'p2sh-segwit')
self.log.info('getrawchangeaddress defaults to addresstype if -changetype is not set and argument is absent')
self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32')
diff --git a/test/functional/wallet_avoid_mixing_output_types.py b/test/functional/wallet_avoid_mixing_output_types.py
new file mode 100755
index 0000000000..cad9d02808
--- /dev/null
+++ b/test/functional/wallet_avoid_mixing_output_types.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or https://www.opensource.org/licenses/mit-license.php.
+"""Test output type mixing during coin selection
+
+A wallet may have different types of UTXOs to choose from during coin selection,
+where output type is one of the following:
+ - BECH32M
+ - BECH32
+ - P2SH-SEGWIT
+ - LEGACY
+
+This test verifies that mixing different output types is avoided unless
+absolutely necessary. Both wallets start with zero funds. Alice mines
+enough blocks to have spendable coinbase outputs. Alice sends three
+random value payments which sum to 10BTC for each output type to Bob,
+for a total of 40BTC in Bob's wallet.
+
+Bob then sends random valued payments back to Alice, some of which need
+unconfirmed change, and we verify that none of these payments contain mixed
+inputs. Finally, Bob sends the remainder of his funds, which requires mixing.
+
+The payment values are random, but chosen such that they sum up to a specified
+total. This ensures we are not relying on specific values for the UTXOs,
+but still know when to expect mixing due to the wallet being close to empty.
+
+"""
+
+import random
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.blocktools import COINBASE_MATURITY
+
+ADDRESS_TYPES = [
+ "bech32m",
+ "bech32",
+ "p2sh-segwit",
+ "legacy",
+]
+
+
+def is_bech32_address(node, addr):
+ """Check if an address contains a bech32 output."""
+ addr_info = node.getaddressinfo(addr)
+ return addr_info['desc'].startswith('wpkh(')
+
+
+def is_bech32m_address(node, addr):
+ """Check if an address contains a bech32m output."""
+ addr_info = node.getaddressinfo(addr)
+ return addr_info['desc'].startswith('tr(')
+
+
+def is_p2sh_segwit_address(node, addr):
+ """Check if an address contains a P2SH-Segwit output.
+ Note: this function does not actually determine the type
+ of P2SH output, but is sufficient for this test in that
+ we are only generating P2SH-Segwit outputs.
+ """
+ addr_info = node.getaddressinfo(addr)
+ return addr_info['desc'].startswith('sh(wpkh(')
+
+
+def is_legacy_address(node, addr):
+ """Check if an address contains a legacy output."""
+ addr_info = node.getaddressinfo(addr)
+ return addr_info['desc'].startswith('pkh(')
+
+
+def is_same_type(node, tx):
+ """Check that all inputs are of the same OutputType"""
+ vins = node.getrawtransaction(tx, True)['vin']
+ inputs = []
+ for vin in vins:
+ prev_tx, n = vin['txid'], vin['vout']
+ inputs.append(
+ node.getrawtransaction(
+ prev_tx,
+ True,
+ )['vout'][n]['scriptPubKey']['address']
+ )
+ has_legacy = False
+ has_p2sh = False
+ has_bech32 = False
+ has_bech32m = False
+
+ for addr in inputs:
+ if is_legacy_address(node, addr):
+ has_legacy = True
+ if is_p2sh_segwit_address(node, addr):
+ has_p2sh = True
+ if is_bech32_address(node, addr):
+ has_bech32 = True
+ if is_bech32m_address(node, addr):
+ has_bech32m = True
+
+ return (sum([has_legacy, has_p2sh, has_bech32, has_bech32m]) == 1)
+
+
+def generate_payment_values(n, m):
+ """Return a randomly chosen list of n positive integers summing to m.
+ Each such list is equally likely to occur."""
+
+ dividers = sorted(random.sample(range(1, m), n - 1))
+ return [a - b for a, b in zip(dividers + [m], [0] + dividers)]
+
+
+class AddressInputTypeGrouping(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 2
+ self.extra_args = [
+ [
+ "-addresstype=bech32",
+ "-whitelist=noban@127.0.0.1",
+ "-txindex",
+ ],
+ [
+ "-addresstype=p2sh-segwit",
+ "-whitelist=noban@127.0.0.1",
+ "-txindex",
+ ],
+ ]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+ self.skip_if_no_sqlite()
+
+ def make_payment(self, A, B, v, addr_type):
+ fee_rate = random.randint(1, 20)
+ self.log.debug(f"Making payment of {v} BTC at fee_rate {fee_rate}")
+ tx = B.sendtoaddress(
+ address=A.getnewaddress(address_type=addr_type),
+ amount=v,
+ fee_rate=fee_rate,
+ )
+ return tx
+
+ def run_test(self):
+
+ # alias self.nodes[i] to A, B for readability
+ A, B = self.nodes[0], self.nodes[1]
+ self.generate(A, COINBASE_MATURITY + 5)
+
+ self.log.info("Creating mixed UTXOs in B's wallet")
+ for v in generate_payment_values(3, 10):
+ self.log.debug(f"Making payment of {v} BTC to legacy")
+ A.sendtoaddress(B.getnewaddress(address_type="legacy"), v)
+
+ for v in generate_payment_values(3, 10):
+ self.log.debug(f"Making payment of {v} BTC to p2sh")
+ A.sendtoaddress(B.getnewaddress(address_type="p2sh-segwit"), v)
+
+ for v in generate_payment_values(3, 10):
+ self.log.debug(f"Making payment of {v} BTC to bech32")
+ A.sendtoaddress(B.getnewaddress(address_type="bech32"), v)
+
+ for v in generate_payment_values(3, 10):
+ self.log.debug(f"Making payment of {v} BTC to bech32m")
+ A.sendtoaddress(B.getnewaddress(address_type="bech32m"), v)
+
+ self.generate(A, 1)
+
+ self.log.info("Sending payments from B to A")
+ for v in generate_payment_values(5, 9):
+ tx = self.make_payment(
+ A, B, v, random.choice(ADDRESS_TYPES)
+ )
+ self.generate(A, 1)
+ assert is_same_type(B, tx)
+
+ tx = self.make_payment(A, B, 30.99, random.choice(ADDRESS_TYPES))
+ assert not is_same_type(B, tx)
+
+
+if __name__ == '__main__':
+ AddressInputTypeGrouping().main()
diff --git a/test/functional/wallet_balance.py b/test/functional/wallet_balance.py
index 0c93821e7f..ec58ace4a2 100755
--- a/test/functional/wallet_balance.py
+++ b/test/functional/wallet_balance.py
@@ -55,6 +55,9 @@ class WalletTest(BitcoinTestFramework):
['-limitdescendantcount=3', '-walletrejectlongchains=0'],
[],
]
+ # whitelist peers to speed up tx relay / mempool sync
+ for args in self.extra_args:
+ args.append("-whitelist=noban@127.0.0.1")
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -263,7 +266,6 @@ class WalletTest(BitcoinTestFramework):
self.nodes[1].invalidateblock(block_reorg)
assert_equal(self.nodes[0].getbalance(minconf=0), 0) # wallet txs not in the mempool are untrusted
self.generatetoaddress(self.nodes[0], 1, ADDRESS_WATCHONLY, sync_fun=self.no_op)
- assert_equal(self.nodes[0].getbalance(minconf=0), 0) # wallet txs not in the mempool are untrusted
# Now confirm tx_orig
self.restart_node(1, ['-persistmempool=0'])
@@ -273,6 +275,26 @@ class WalletTest(BitcoinTestFramework):
self.generatetoaddress(self.nodes[1], 1, ADDRESS_WATCHONLY)
assert_equal(self.nodes[0].getbalance(minconf=0), total_amount + 1) # The reorg recovered our fee of 1 coin
+ if not self.options.descriptors:
+ self.log.info('Check if mempool is taken into account after import*')
+ address = self.nodes[0].getnewaddress()
+ privkey = self.nodes[0].dumpprivkey(address)
+ self.nodes[0].sendtoaddress(address, 0.1)
+ self.nodes[0].unloadwallet('')
+ # check importaddress on fresh wallet
+ self.nodes[0].createwallet('w1', False, True)
+ self.nodes[0].importaddress(address)
+ assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], 0)
+ assert_equal(self.nodes[0].getbalances()['watchonly']['untrusted_pending'], Decimal('0.1'))
+ self.nodes[0].importprivkey(privkey)
+ assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], Decimal('0.1'))
+ assert_equal(self.nodes[0].getbalances()['watchonly']['untrusted_pending'], 0)
+ self.nodes[0].unloadwallet('w1')
+ # check importprivkey on fresh wallet
+ self.nodes[0].createwallet('w2', False, True)
+ self.nodes[0].importprivkey(privkey)
+ assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], Decimal('0.1'))
+
if __name__ == '__main__':
WalletTest().main()
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index a6c93ba5f9..917721fef8 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -7,6 +7,7 @@ from decimal import Decimal
from itertools import product
from test_framework.blocktools import COINBASE_MATURITY
+from test_framework.descriptors import descsum_create
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_array_result,
@@ -25,7 +26,7 @@ class WalletTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
self.extra_args = [[
- "-acceptnonstdtxn=1", "-walletrejectlongchains=0"
+ "-dustrelayfee=0", "-walletrejectlongchains=0", "-whitelist=noban@127.0.0.1"
]] * self.num_nodes
self.setup_clean_chain = True
self.supports_cli = False
@@ -414,7 +415,7 @@ class WalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4")
# This will raise an exception since generate does not accept a string
- assert_raises_rpc_error(-1, "not an integer", self.generate, self.nodes[0], "2")
+ assert_raises_rpc_error(-1, "not of expected type number", self.generate, self.nodes[0], "2")
if not self.options.descriptors:
@@ -584,15 +585,9 @@ class WalletTest(BitcoinTestFramework):
# ==Check that wallet prefers to use coins that don't exceed mempool limits =====
- # Get all non-zero utxos together
+ # Get all non-zero utxos together and split into two chains
chain_addrs = [self.nodes[0].getnewaddress(), self.nodes[0].getnewaddress()]
- singletxid = self.nodes[0].sendtoaddress(chain_addrs[0], self.nodes[0].getbalance(), "", "", True)
- self.generate(self.nodes[0], 1, sync_fun=self.no_op)
- node0_balance = self.nodes[0].getbalance()
- # Split into two chains
- rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], {chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')})
- signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx)
- singletxid = self.nodes[0].sendrawtransaction(hexstring=signedtx["hex"], maxfeerate=0)
+ self.nodes[0].sendall(recipients=chain_addrs)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
# Make a long chain of unconfirmed payments without hitting mempool limit
@@ -700,6 +695,39 @@ class WalletTest(BitcoinTestFramework):
txid_feeReason_four = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=False)
assert_equal(self.nodes[2].gettransaction(txid_feeReason_four)['txid'], txid_feeReason_four)
+ if self.options.descriptors:
+ self.log.info("Testing 'listunspent' outputs the parent descriptor(s) of coins")
+ # Create two multisig descriptors, and send a UTxO each.
+ multi_a = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YBNjUo96Jxd1u4XKWgnoc7LsA1jz3Yc2NiDbhtfBhaBtemB73n9V5vtJHwU6FVXwggTbeoJWQ1rzdz8ysDuQkpnaHyvnvzR/*,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*))")
+ multi_b = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*,tpubD6NzVbkrYhZ4Y2RLiuEzNQkntjmsLpPYDm3LTRBYynUQtDtpzeUKAcb9sYthSFL3YR74cdFgF5mW8yKxv2W2CWuZDFR2dUpE5PF9kbrVXNZ/*))")
+ addr_a = self.nodes[0].deriveaddresses(multi_a, 0)[0]
+ addr_b = self.nodes[0].deriveaddresses(multi_b, 0)[0]
+ txid_a = self.nodes[0].sendtoaddress(addr_a, 0.01)
+ txid_b = self.nodes[0].sendtoaddress(addr_b, 0.01)
+ self.generate(self.nodes[0], 1, sync_fun=self.no_op)
+ # Now import the descriptors, make sure we can identify on which descriptor each coin was received.
+ self.nodes[0].createwallet(wallet_name="wo", descriptors=True, disable_private_keys=True)
+ wo_wallet = self.nodes[0].get_wallet_rpc("wo")
+ wo_wallet.importdescriptors([
+ {
+ "desc": multi_a,
+ "active": False,
+ "timestamp": "now",
+ },
+ {
+ "desc": multi_b,
+ "active": False,
+ "timestamp": "now",
+ },
+ ])
+ coins = wo_wallet.listunspent(minconf=0)
+ assert_equal(len(coins), 2)
+ coin_a = next(c for c in coins if c["txid"] == txid_a)
+ assert_equal(coin_a["parent_descs"][0], multi_a)
+ coin_b = next(c for c in coins if c["txid"] == txid_b)
+ assert_equal(coin_b["parent_descs"][0], multi_b)
+ self.nodes[0].unloadwallet("wo")
+
if __name__ == '__main__':
WalletTest().main()
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index 3b23ee8e94..f4ae697292 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -23,7 +23,7 @@ from test_framework.blocktools import (
send_to_witness,
)
from test_framework.messages import (
- BIP125_SEQUENCE_NUMBER,
+ MAX_BIP125_RBF_SEQUENCE,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -53,6 +53,7 @@ class BumpFeeTest(BitcoinTestFramework):
"-walletrbf={}".format(i),
"-mintxfee=0.00002",
"-addresstype=bech32",
+ "-whitelist=noban@127.0.0.1",
] for i in range(self.num_nodes)]
def skip_test_if_missing_module(self):
@@ -86,7 +87,7 @@ class BumpFeeTest(BitcoinTestFramework):
self.test_invalid_parameters(rbf_node, peer_node, dest_address)
test_segwit_bumpfee_succeeds(self, rbf_node, dest_address)
test_nonrbf_bumpfee_fails(self, peer_node, dest_address)
- test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address)
+ test_notmine_bumpfee(self, rbf_node, peer_node, dest_address)
test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_address)
test_dust_to_fee(self, rbf_node, dest_address)
test_watchonly_psbt(self, peer_node, rbf_node, dest_address)
@@ -212,7 +213,7 @@ def test_segwit_bumpfee_succeeds(self, rbf_node, dest_address):
rbfraw = rbf_node.createrawtransaction([{
'txid': segwitid,
'vout': 0,
- "sequence": BIP125_SEQUENCE_NUMBER
+ "sequence": MAX_BIP125_RBF_SEQUENCE
}], {dest_address: Decimal("0.0005"),
rbf_node.getrawchangeaddress(): Decimal("0.0003")})
rbfsigned = rbf_node.signrawtransactionwithwallet(rbfraw)
@@ -232,7 +233,7 @@ def test_nonrbf_bumpfee_fails(self, peer_node, dest_address):
self.clear_mempool()
-def test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address):
+def test_notmine_bumpfee(self, rbf_node, peer_node, dest_address):
self.log.info('Test that it cannot bump fee if non-owned inputs are included')
# here, the rbftx has a peer_node coin and then adds a rbf_node input
# Note that this test depends upon the RPC code checking input ownership prior to change outputs
@@ -243,15 +244,34 @@ def test_notmine_bumpfee_fails(self, rbf_node, peer_node, dest_address):
"txid": utxo["txid"],
"vout": utxo["vout"],
"address": utxo["address"],
- "sequence": BIP125_SEQUENCE_NUMBER
+ "sequence": MAX_BIP125_RBF_SEQUENCE
} for utxo in utxos]
output_val = sum(utxo["amount"] for utxo in utxos) - fee
rawtx = rbf_node.createrawtransaction(inputs, {dest_address: output_val})
signedtx = rbf_node.signrawtransactionwithwallet(rawtx)
signedtx = peer_node.signrawtransactionwithwallet(signedtx["hex"])
rbfid = rbf_node.sendrawtransaction(signedtx["hex"])
+ entry = rbf_node.getmempoolentry(rbfid)
+ old_fee = entry["fees"]["base"]
+ old_feerate = int(old_fee / entry["vsize"] * Decimal(1e8))
assert_raises_rpc_error(-4, "Transaction contains inputs that don't belong to this wallet",
rbf_node.bumpfee, rbfid)
+
+ def finish_psbtbumpfee(psbt):
+ psbt = rbf_node.walletprocesspsbt(psbt)
+ psbt = peer_node.walletprocesspsbt(psbt["psbt"])
+ final = rbf_node.finalizepsbt(psbt["psbt"])
+ res = rbf_node.testmempoolaccept([final["hex"]])
+ assert res[0]["allowed"]
+ assert_greater_than(res[0]["fees"]["base"], old_fee)
+
+ self.log.info("Test that psbtbumpfee works for non-owned inputs")
+ psbt = rbf_node.psbtbumpfee(txid=rbfid)
+ finish_psbtbumpfee(psbt["psbt"])
+
+ psbt = rbf_node.psbtbumpfee(txid=rbfid, options={"fee_rate": old_feerate + 10})
+ finish_psbtbumpfee(psbt["psbt"])
+
self.clear_mempool()
@@ -578,7 +598,7 @@ def test_change_script_match(self, rbf_node, dest_address):
def spend_one_input(node, dest_address, change_size=Decimal("0.00049000")):
tx_input = dict(
- sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
+ sequence=MAX_BIP125_RBF_SEQUENCE, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000")))
destinations = {dest_address: Decimal("0.00050000")}
if change_size > 0:
destinations[node.getrawchangeaddress()] = change_size
@@ -604,7 +624,7 @@ def test_no_more_inputs_fails(self, rbf_node, dest_address):
# feerate rbf requires confirmed outputs when change output doesn't exist or is insufficient
self.generatetoaddress(rbf_node, 1, dest_address)
# spend all funds, no change output
- rbfid = rbf_node.sendtoaddress(rbf_node.getnewaddress(), rbf_node.getbalance(), "", "", True)
+ rbfid = rbf_node.sendall(recipients=[rbf_node.getnewaddress()])['txid']
assert_raises_rpc_error(-4, "Unable to create transaction. Insufficient funds", rbf_node.bumpfee, rbfid)
self.clear_mempool()
diff --git a/test/functional/wallet_coinbase_category.py b/test/functional/wallet_coinbase_category.py
index 5a6b6cee59..c2a8e612cf 100755
--- a/test/functional/wallet_coinbase_category.py
+++ b/test/functional/wallet_coinbase_category.py
@@ -15,6 +15,7 @@ from test_framework.util import (
class CoinbaseCategoryTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.setup_clean_chain = True
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_encryption.py b/test/functional/wallet_encryption.py
index 0c9106f800..37c1c4bff3 100755
--- a/test/functional/wallet_encryption.py
+++ b/test/functional/wallet_encryption.py
@@ -9,8 +9,7 @@ import time
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_raises_rpc_error,
- assert_greater_than,
- assert_greater_than_or_equal,
+ assert_equal,
)
@@ -76,21 +75,18 @@ class WalletEncryptionTest(BitcoinTestFramework):
self.log.info('Check a timeout less than the limit')
MAX_VALUE = 100000000
- expected_time = int(time.time()) + MAX_VALUE - 600
+ now = int(time.time())
+ self.nodes[0].setmocktime(now)
+ expected_time = now + MAX_VALUE - 600
self.nodes[0].walletpassphrase(passphrase2, MAX_VALUE - 600)
- # give buffer for walletpassphrase, since it iterates over all encrypted keys
- expected_time_with_buffer = time.time() + MAX_VALUE - 600
actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
- assert_greater_than_or_equal(actual_time, expected_time)
- assert_greater_than(expected_time_with_buffer, actual_time)
+ assert_equal(actual_time, expected_time)
self.log.info('Check a timeout greater than the limit')
- expected_time = int(time.time()) + MAX_VALUE - 1
+ expected_time = now + MAX_VALUE
self.nodes[0].walletpassphrase(passphrase2, MAX_VALUE + 1000)
- expected_time_with_buffer = time.time() + MAX_VALUE
actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
- assert_greater_than_or_equal(actual_time, expected_time)
- assert_greater_than(expected_time_with_buffer, actual_time)
+ assert_equal(actual_time, expected_time)
if __name__ == '__main__':
diff --git a/test/functional/wallet_groups.py b/test/functional/wallet_groups.py
index eb305c5fa2..e5e4cf03bf 100755
--- a/test/functional/wallet_groups.py
+++ b/test/functional/wallet_groups.py
@@ -26,6 +26,11 @@ class WalletGroupTest(BitcoinTestFramework):
["-maxapsfee=0.00002719"],
["-maxapsfee=0.00002720"],
]
+
+ for args in self.extra_args:
+ args.append("-whitelist=noban@127.0.0.1") # whitelist peers to speed up tx relay / mempool sync
+ args.append(f"-paytxfee={20 * 1e3 / 1e8}") # apply feerate of 20 sats/vB across all nodes
+
self.rpc_timeout = 480
def skip_test_if_missing_module(self):
@@ -150,7 +155,7 @@ class WalletGroupTest(BitcoinTestFramework):
assert_equal(2, len(tx6["vout"]))
# Empty out node2's wallet
- self.nodes[2].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=self.nodes[2].getbalance(), subtractfeefromamount=True)
+ self.nodes[2].sendall(recipients=[self.nodes[0].getnewaddress()])
self.sync_all()
self.generate(self.nodes[0], 1)
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index ac878ea0aa..6c41b468b6 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -20,6 +20,10 @@ class WalletHDTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
self.extra_args = [[], ['-keypool=0']]
+ # whitelist peers to speed up tx relay / mempool sync
+ for args in self.extra_args:
+ args.append("-whitelist=noban@127.0.0.1")
+
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -173,8 +177,8 @@ class WalletHDTest(BitcoinTestFramework):
# Sethdseed parameter validity
assert_raises_rpc_error(-1, 'sethdseed', self.nodes[0].sethdseed, False, new_seed, 0)
assert_raises_rpc_error(-5, "Invalid private key", self.nodes[1].sethdseed, False, "not_wif")
- assert_raises_rpc_error(-1, "JSON value is not a boolean as expected", self.nodes[1].sethdseed, "Not_bool")
- assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[1].sethdseed, False, True)
+ assert_raises_rpc_error(-1, "JSON value of type string is not of expected type bool", self.nodes[1].sethdseed, "Not_bool")
+ assert_raises_rpc_error(-1, "JSON value of type bool is not of expected type string", self.nodes[1].sethdseed, False, True)
assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, new_seed)
assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress()))
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index d9acc8cea5..085ad51c79 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -87,6 +87,7 @@ class Variant(collections.namedtuple("Variant", "call data address_type rescan p
assert_equal(len(txs), self.expected_txs)
addresses = self.node.listreceivedbyaddress(minconf=0, include_watchonly=True, address_filter=self.address['address'])
+
if self.expected_txs:
assert_equal(len(addresses[0]["txids"]), self.expected_txs)
@@ -98,13 +99,18 @@ class Variant(collections.namedtuple("Variant", "call data address_type rescan p
assert_equal(tx["category"], "receive")
assert_equal(tx["label"], self.label)
assert_equal(tx["txid"], txid)
- assert_equal(tx["confirmations"], 1 + current_height - confirmation_height)
- assert "trusted" not in tx
+
+ # If no confirmation height is given, the tx is still in the
+ # mempool.
+ confirmations = (1 + current_height - confirmation_height) if confirmation_height else 0
+ assert_equal(tx["confirmations"], confirmations)
+ if confirmations:
+ assert "trusted" not in tx
address, = [ad for ad in addresses if txid in ad["txids"]]
assert_equal(address["address"], self.address["address"])
assert_equal(address["amount"], self.expected_balance)
- assert_equal(address["confirmations"], 1 + current_height - confirmation_height)
+ assert_equal(address["confirmations"], confirmations)
# Verify the transaction is correctly marked watchonly depending on
# whether the transaction pays to an imported public key or
# imported private key. The test setup ensures that transaction
@@ -162,11 +168,12 @@ class ImportRescanTest(BitcoinTestFramework):
self.import_deterministic_coinbase_privkeys()
self.stop_nodes()
- self.start_nodes()
+ self.start_nodes(extra_args=[["-whitelist=noban@127.0.0.1"]] * self.num_nodes)
for i in range(1, self.num_nodes):
self.connect_nodes(i, 0)
def run_test(self):
+
# Create one transaction on node 0 with a unique amount for
# each possible type of wallet import RPC.
for i, variant in enumerate(IMPORT_VARIANTS):
@@ -207,7 +214,7 @@ class ImportRescanTest(BitcoinTestFramework):
variant.check()
# Create new transactions sending to each address.
- for i, variant in enumerate(IMPORT_VARIANTS):
+ for variant in IMPORT_VARIANTS:
variant.sent_amount = get_rand_amount()
variant.sent_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.sent_amount)
self.generate(self.nodes[0], 1) # Generate one block for each send
@@ -223,6 +230,46 @@ class ImportRescanTest(BitcoinTestFramework):
variant.expected_txs += 1
variant.check(variant.sent_txid, variant.sent_amount, variant.confirmation_height)
+ self.log.info('Test that the mempool is rescanned as well if the rescan parameter is set to true')
+
+ # The late timestamp and pruned variants are not necessary when testing mempool rescan
+ mempool_variants = [variant for variant in IMPORT_VARIANTS if variant.rescan != Rescan.late_timestamp and not variant.prune]
+ # No further blocks are mined so the timestamp will stay the same
+ timestamp = self.nodes[0].getblockheader(self.nodes[0].getbestblockhash())["time"]
+
+ # Create one transaction on node 0 with a unique amount for
+ # each possible type of wallet import RPC.
+ for i, variant in enumerate(mempool_variants):
+ variant.label = "mempool label {} {}".format(i, variant)
+ variant.address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress(
+ label=variant.label,
+ address_type=variant.address_type.value,
+ ))
+ variant.key = self.nodes[1].dumpprivkey(variant.address["address"])
+ variant.initial_amount = get_rand_amount()
+ variant.initial_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.initial_amount)
+ variant.confirmation_height = 0
+ variant.timestamp = timestamp
+
+ assert_equal(len(self.nodes[0].getrawmempool()), len(mempool_variants))
+ self.sync_mempools()
+
+ # For each variation of wallet key import, invoke the import RPC and
+ # check the results from getbalance and listtransactions.
+ for variant in mempool_variants:
+ self.log.info('Run import for mempool variant {}'.format(variant))
+ expect_rescan = variant.rescan == Rescan.yes
+ variant.node = self.nodes[2 + IMPORT_NODES.index(ImportNode(variant.prune, expect_rescan))]
+ variant.do_import(variant.timestamp)
+ if expect_rescan:
+ variant.expected_balance = variant.initial_amount
+ variant.expected_txs = 1
+ variant.check(variant.initial_txid, variant.initial_amount)
+ else:
+ variant.expected_balance = 0
+ variant.expected_txs = 0
+ variant.check()
+
if __name__ == "__main__":
ImportRescanTest().main()
diff --git a/test/functional/wallet_importdescriptors.py b/test/functional/wallet_importdescriptors.py
index ac74ff2484..9744009af8 100755
--- a/test/functional/wallet_importdescriptors.py
+++ b/test/functional/wallet_importdescriptors.py
@@ -35,6 +35,9 @@ class ImportDescriptorsTest(BitcoinTestFramework):
self.extra_args = [["-addresstype=legacy"],
["-addresstype=bech32", "-keypool=5"]
]
+ # whitelist peers to speed up tx relay / mempool sync
+ for args in self.extra_args:
+ args.append("-whitelist=noban@127.0.0.1")
self.setup_clean_chain = True
self.wallet_names = []
@@ -454,7 +457,7 @@ class ImportDescriptorsTest(BitcoinTestFramework):
send_txid = wmulti_priv.sendtoaddress(w0.getnewaddress(), 8)
decoded = wmulti_priv.gettransaction(txid=send_txid, verbose=True)['decoded']
assert_equal(len(decoded['vin'][0]['txinwitness']), 4)
- self.generate(self.nodes[0], 6)
+ self.sync_all()
self.nodes[1].createwallet(wallet_name="wmulti_pub", disable_private_keys=True, blank=True, descriptors=True)
wmulti_pub = self.nodes[1].get_wallet_rpc("wmulti_pub")
@@ -480,7 +483,9 @@ class ImportDescriptorsTest(BitcoinTestFramework):
addr = wmulti_pub.getnewaddress('', 'bech32')
assert_equal(addr, 'bcrt1qp8s25ckjl7gr6x2q3dx3tn2pytwp05upkjztk6ey857tt50r5aeqn6mvr9') # Derived at m/84'/0'/0'/1
change_addr = wmulti_pub.getrawchangeaddress('bech32')
- assert_equal(change_addr, 'bcrt1qt9uhe3a9hnq7vajl7a094z4s3crm9ttf8zw3f5v9gr2nyd7e3lnsy44n8e')
+ assert_equal(change_addr, 'bcrt1qzxl0qz2t88kljdnkzg4n4gapr6kte26390gttrg79x66nt4p04fssj53nl')
+ assert(send_txid in self.nodes[0].getrawmempool(True))
+ assert(send_txid in (x['txid'] for x in wmulti_pub.listunspent(0)))
assert_equal(wmulti_pub.getwalletinfo()['keypoolsize'], 999)
# generate some utxos for next tests
diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py
index db1d8eb54a..f1d7de2f27 100755
--- a/test/functional/wallet_listreceivedby.py
+++ b/test/functional/wallet_listreceivedby.py
@@ -18,6 +18,8 @@ from test_framework.wallet_util import test_address
class ReceivedByTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ # whitelist peers to speed up tx relay / mempool sync
+ self.extra_args = [["-whitelist=noban@127.0.0.1"]] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -57,6 +59,11 @@ class ReceivedByTest(BitcoinTestFramework):
{"address": empty_addr},
{"address": empty_addr, "label": "", "amount": 0, "confirmations": 0, "txids": []})
+ # No returned addy should be a change addr
+ for node in self.nodes:
+ for addr_obj in node.listreceivedbyaddress():
+ assert_equal(node.getaddressinfo(addr_obj["address"])["ischange"], False)
+
# Test Address filtering
# Only on addr
expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]}
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index fc06565983..aff408ceb1 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -6,9 +6,10 @@
from test_framework.address import key_to_p2wpkh
from test_framework.blocktools import COINBASE_MATURITY
+from test_framework.descriptors import descsum_create
from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.messages import BIP125_SEQUENCE_NUMBER
+from test_framework.messages import MAX_BIP125_RBF_SEQUENCE
from test_framework.util import (
assert_array_result,
assert_equal,
@@ -22,6 +23,8 @@ class ListSinceBlockTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
self.setup_clean_chain = True
+ # whitelist peers to speed up tx relay / mempool sync
+ self.extra_args = [["-whitelist=noban@127.0.0.1"]] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -39,6 +42,10 @@ class ListSinceBlockTest(BitcoinTestFramework):
self.test_double_send()
self.double_spends_filtered()
self.test_targetconfirmations()
+ if self.options.descriptors:
+ self.test_desc()
+ self.test_send_to_self()
+ self.test_op_return()
def test_no_blockhash(self):
self.log.info("Test no blockhash")
@@ -346,7 +353,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
dest_address = spending_node.getnewaddress()
tx_input = dict(
- sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in spending_node.listunspent()))
+ sequence=MAX_BIP125_RBF_SEQUENCE, **next(u for u in spending_node.listunspent()))
rawtx = spending_node.createrawtransaction(
[tx_input], {dest_address: tx_input["amount"] - Decimal("0.00051000"),
spending_node.getrawchangeaddress(): Decimal("0.00050000")})
@@ -383,5 +390,78 @@ class ListSinceBlockTest(BitcoinTestFramework):
assert_equal(original_found, False)
assert_equal(double_found, False)
+ def test_desc(self):
+ """Make sure we can track coins by descriptor."""
+ self.log.info("Test descriptor lookup by scriptPubKey.")
+
+ # Create a watchonly wallet tracking two multisig descriptors.
+ multi_a = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YBNjUo96Jxd1u4XKWgnoc7LsA1jz3Yc2NiDbhtfBhaBtemB73n9V5vtJHwU6FVXwggTbeoJWQ1rzdz8ysDuQkpnaHyvnvzR/*,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*))")
+ multi_b = descsum_create("wsh(multi(1,tpubD6NzVbkrYhZ4YHdDGMAYGaWxMSC1B6tPRTHuU5t3BcfcS3nrF523iFm5waFd1pP3ZvJt4Jr8XmCmsTBNx5suhcSgtzpGjGMASR3tau1hJz4/*,tpubD6NzVbkrYhZ4Y2RLiuEzNQkntjmsLpPYDm3LTRBYynUQtDtpzeUKAcb9sYthSFL3YR74cdFgF5mW8yKxv2W2CWuZDFR2dUpE5PF9kbrVXNZ/*))")
+ self.nodes[0].createwallet(wallet_name="wo", descriptors=True, disable_private_keys=True)
+ wo_wallet = self.nodes[0].get_wallet_rpc("wo")
+ wo_wallet.importdescriptors([
+ {
+ "desc": multi_a,
+ "active": False,
+ "timestamp": "now",
+ },
+ {
+ "desc": multi_b,
+ "active": False,
+ "timestamp": "now",
+ },
+ ])
+
+ # Send a coin to each descriptor.
+ assert_equal(len(wo_wallet.listsinceblock()["transactions"]), 0)
+ addr_a = self.nodes[0].deriveaddresses(multi_a, 0)[0]
+ addr_b = self.nodes[0].deriveaddresses(multi_b, 0)[0]
+ self.nodes[2].sendtoaddress(addr_a, 1)
+ self.nodes[2].sendtoaddress(addr_b, 2)
+ self.generate(self.nodes[2], 1)
+
+ # We can identify on which descriptor each coin was received.
+ coins = wo_wallet.listsinceblock()["transactions"]
+ assert_equal(len(coins), 2)
+ coin_a = next(c for c in coins if c["amount"] == 1)
+ assert_equal(coin_a["parent_descs"][0], multi_a)
+ coin_b = next(c for c in coins if c["amount"] == 2)
+ assert_equal(coin_b["parent_descs"][0], multi_b)
+
+ def test_send_to_self(self):
+ """We can make listsinceblock output our change outputs."""
+ self.log.info("Test the inclusion of change outputs in the output.")
+
+ # Create a UTxO paying to one of our change addresses.
+ block_hash = self.nodes[2].getbestblockhash()
+ addr = self.nodes[2].getrawchangeaddress()
+ self.nodes[2].sendtoaddress(addr, 1)
+
+ # If we don't list change, we won't have an entry for it.
+ coins = self.nodes[2].listsinceblock(blockhash=block_hash)["transactions"]
+ assert not any(c["address"] == addr for c in coins)
+
+ # Now if we list change, we'll get both the send (to a change address) and
+ # the actual change.
+ res = self.nodes[2].listsinceblock(blockhash=block_hash, include_change=True)
+ coins = [entry for entry in res["transactions"] if entry["category"] == "receive"]
+ assert_equal(len(coins), 2)
+ assert any(c["address"] == addr for c in coins)
+ assert all(self.nodes[2].getaddressinfo(c["address"])["ischange"] for c in coins)
+
+ def test_op_return(self):
+ """Test if OP_RETURN outputs will be displayed correctly."""
+ block_hash = self.nodes[2].getbestblockhash()
+
+ raw_tx = self.nodes[2].createrawtransaction([], [{'data': 'aa'}])
+ funded_tx = self.nodes[2].fundrawtransaction(raw_tx)
+ signed_tx = self.nodes[2].signrawtransactionwithwallet(funded_tx['hex'])
+ tx_id = self.nodes[2].sendrawtransaction(signed_tx['hex'])
+
+ op_ret_tx = [tx for tx in self.nodes[2].listsinceblock(blockhash=block_hash)["transactions"] if tx['txid'] == tx_id][0]
+
+ assert 'address' not in op_ret_tx
+
+
if __name__ == '__main__':
ListSinceBlockTest().main()
diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py
index f75877f256..9bb06774a5 100755
--- a/test/functional/wallet_listtransactions.py
+++ b/test/functional/wallet_listtransactions.py
@@ -25,7 +25,7 @@ class ListTransactionsTest(BitcoinTestFramework):
self.num_nodes = 3
# This test isn't testing txn relay/timing, so set whitelist on the
# peers for instant txn relay. This speeds up the test run time 2-3x.
- self.extra_args = [["-whitelist=noban@127.0.0.1"]] * self.num_nodes
+ self.extra_args = [["-whitelist=noban@127.0.0.1", "-walletrbf=0"]] * self.num_nodes
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -109,6 +109,7 @@ class ListTransactionsTest(BitcoinTestFramework):
self.run_rbf_opt_in_test()
self.run_externally_generated_address_test()
self.run_invalid_parameters_test()
+ self.test_op_return()
def run_rbf_opt_in_test(self):
"""Test the opt-in-rbf flag for sent and received transactions."""
@@ -146,7 +147,7 @@ class ListTransactionsTest(BitcoinTestFramework):
# Create tx2 using createrawtransaction
inputs = [{"txid": utxo_to_use["txid"], "vout": utxo_to_use["vout"]}]
outputs = {self.nodes[0].getnewaddress(): 0.999}
- tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
+ tx2 = self.nodes[1].createrawtransaction(inputs=inputs, outputs=outputs, replaceable=False)
tx2_signed = self.nodes[1].signrawtransactionwithwallet(tx2)["hex"]
txid_2 = self.nodes[1].sendrawtransaction(tx2_signed)
@@ -178,7 +179,7 @@ class ListTransactionsTest(BitcoinTestFramework):
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
inputs = [{"txid": txid_3, "vout": utxo_to_use["vout"]}]
outputs = {self.nodes[0].getnewaddress(): 0.997}
- tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
+ tx4 = self.nodes[1].createrawtransaction(inputs=inputs, outputs=outputs, replaceable=False)
tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"]
txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
@@ -284,6 +285,17 @@ class ListTransactionsTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "Negative count", self.nodes[0].listtransactions, count=-1)
assert_raises_rpc_error(-8, "Negative from", self.nodes[0].listtransactions, skip=-1)
+ def test_op_return(self):
+ """Test if OP_RETURN outputs will be displayed correctly."""
+ raw_tx = self.nodes[0].createrawtransaction([], [{'data': 'aa'}])
+ funded_tx = self.nodes[0].fundrawtransaction(raw_tx)
+ signed_tx = self.nodes[0].signrawtransactionwithwallet(funded_tx['hex'])
+ tx_id = self.nodes[0].sendrawtransaction(signed_tx['hex'])
+
+ op_ret_tx = [tx for tx in self.nodes[0].listtransactions() if tx['txid'] == tx_id][0]
+
+ assert 'address' not in op_ret_tx
+
if __name__ == '__main__':
ListTransactionsTest().main()
diff --git a/test/functional/wallet_migration.py b/test/functional/wallet_migration.py
new file mode 100755
index 0000000000..4f060f9960
--- /dev/null
+++ b/test/functional/wallet_migration.py
@@ -0,0 +1,417 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test Migrating a wallet from legacy to descriptor."""
+
+import os
+import random
+from test_framework.descriptors import descsum_create
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+ find_vout_for_address,
+)
+from test_framework.wallet_util import (
+ get_generate_key,
+)
+
+
+class WalletMigrationTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+ self.extra_args = [[]]
+ self.supports_cli = False
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+ self.skip_if_no_sqlite()
+ self.skip_if_no_bdb()
+
+ def assert_is_sqlite(self, wallet_name):
+ wallet_file_path = os.path.join(self.nodes[0].datadir, "regtest/wallets", wallet_name, self.wallet_data_filename)
+ with open(wallet_file_path, 'rb') as f:
+ file_magic = f.read(16)
+ assert_equal(file_magic, b'SQLite format 3\x00')
+ assert_equal(self.nodes[0].get_wallet_rpc(wallet_name).getwalletinfo()["format"], "sqlite")
+
+ def create_legacy_wallet(self, wallet_name):
+ self.nodes[0].createwallet(wallet_name=wallet_name)
+ wallet = self.nodes[0].get_wallet_rpc(wallet_name)
+ assert_equal(wallet.getwalletinfo()["descriptors"], False)
+ assert_equal(wallet.getwalletinfo()["format"], "bdb")
+ return wallet
+
+ def assert_addr_info_equal(self, addr_info, addr_info_old):
+ assert_equal(addr_info["address"], addr_info_old["address"])
+ assert_equal(addr_info["scriptPubKey"], addr_info_old["scriptPubKey"])
+ assert_equal(addr_info["ismine"], addr_info_old["ismine"])
+ assert_equal(addr_info["hdkeypath"], addr_info_old["hdkeypath"])
+ assert_equal(addr_info["solvable"], addr_info_old["solvable"])
+ assert_equal(addr_info["ischange"], addr_info_old["ischange"])
+ assert_equal(addr_info["hdmasterfingerprint"], addr_info_old["hdmasterfingerprint"])
+
+ def assert_list_txs_equal(self, received_list_txs, expected_list_txs):
+ for d in received_list_txs:
+ if "parent_descs" in d:
+ del d["parent_descs"]
+ for d in expected_list_txs:
+ if "parent_descs" in d:
+ del d["parent_descs"]
+ assert_equal(received_list_txs, expected_list_txs)
+
+ def test_basic(self):
+ default = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
+
+ self.log.info("Test migration of a basic keys only wallet without balance")
+ basic0 = self.create_legacy_wallet("basic0")
+
+ addr = basic0.getnewaddress()
+ change = basic0.getrawchangeaddress()
+
+ old_addr_info = basic0.getaddressinfo(addr)
+ old_change_addr_info = basic0.getaddressinfo(change)
+ assert_equal(old_addr_info["ismine"], True)
+ assert_equal(old_addr_info["hdkeypath"], "m/0'/0'/0'")
+ assert_equal(old_change_addr_info["ismine"], True)
+ assert_equal(old_change_addr_info["hdkeypath"], "m/0'/1'/0'")
+
+ # Note: migration could take a while.
+ basic0.migratewallet()
+
+ # Verify created descriptors
+ assert_equal(basic0.getwalletinfo()["descriptors"], True)
+ self.assert_is_sqlite("basic0")
+
+ # The wallet should create the following descriptors:
+ # * BIP32 descriptors in the form of "0'/0'/*" and "0'/1'/*" (2 descriptors)
+ # * BIP44 descriptors in the form of "44'/1'/0'/0/*" and "44'/1'/0'/1/*" (2 descriptors)
+ # * BIP49 descriptors, P2SH(P2WPKH), in the form of "86'/1'/0'/0/*" and "86'/1'/0'/1/*" (2 descriptors)
+ # * BIP84 descriptors, P2WPKH, in the form of "84'/1'/0'/1/*" and "84'/1'/0'/1/*" (2 descriptors)
+ # * BIP86 descriptors, P2TR, in the form of "86'/1'/0'/0/*" and "86'/1'/0'/1/*" (2 descriptors)
+ # * A combo(PK) descriptor for the wallet master key.
+ # So, should have a total of 11 descriptors on it.
+ assert_equal(len(basic0.listdescriptors()["descriptors"]), 11)
+
+ # Compare addresses info
+ addr_info = basic0.getaddressinfo(addr)
+ change_addr_info = basic0.getaddressinfo(change)
+ self.assert_addr_info_equal(addr_info, old_addr_info)
+ self.assert_addr_info_equal(change_addr_info, old_change_addr_info)
+
+ addr_info = basic0.getaddressinfo(basic0.getnewaddress("", "bech32"))
+ assert_equal(addr_info["hdkeypath"], "m/84'/1'/0'/0/0")
+
+ self.log.info("Test migration of a basic keys only wallet with a balance")
+ basic1 = self.create_legacy_wallet("basic1")
+
+ for _ in range(0, 10):
+ default.sendtoaddress(basic1.getnewaddress(), 1)
+
+ self.generate(self.nodes[0], 1)
+
+ for _ in range(0, 5):
+ basic1.sendtoaddress(default.getnewaddress(), 0.5)
+
+ self.generate(self.nodes[0], 1)
+ bal = basic1.getbalance()
+ txs = basic1.listtransactions()
+
+ basic1.migratewallet()
+ assert_equal(basic1.getwalletinfo()["descriptors"], True)
+ self.assert_is_sqlite("basic1")
+ assert_equal(basic1.getbalance(), bal)
+ self.assert_list_txs_equal(basic1.listtransactions(), txs)
+
+ # restart node and verify that everything is still there
+ self.restart_node(0)
+ default = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
+ self.nodes[0].loadwallet("basic1")
+ basic1 = self.nodes[0].get_wallet_rpc("basic1")
+ assert_equal(basic1.getwalletinfo()["descriptors"], True)
+ self.assert_is_sqlite("basic1")
+ assert_equal(basic1.getbalance(), bal)
+ self.assert_list_txs_equal(basic1.listtransactions(), txs)
+
+ self.log.info("Test migration of a wallet with balance received on the seed")
+ basic2 = self.create_legacy_wallet("basic2")
+ basic2_seed = get_generate_key()
+ basic2.sethdseed(True, basic2_seed.privkey)
+ assert_equal(basic2.getbalance(), 0)
+
+ # Receive coins on different output types for the same seed
+ basic2_balance = 0
+ for addr in [basic2_seed.p2pkh_addr, basic2_seed.p2wpkh_addr, basic2_seed.p2sh_p2wpkh_addr]:
+ send_value = random.randint(1, 4)
+ default.sendtoaddress(addr, send_value)
+ basic2_balance += send_value
+ self.generate(self.nodes[0], 1)
+ assert_equal(basic2.getbalance(), basic2_balance)
+ basic2_txs = basic2.listtransactions()
+
+ # Now migrate and test that we still see have the same balance/transactions
+ basic2.migratewallet()
+ assert_equal(basic2.getwalletinfo()["descriptors"], True)
+ self.assert_is_sqlite("basic2")
+ assert_equal(basic2.getbalance(), basic2_balance)
+ self.assert_list_txs_equal(basic2.listtransactions(), basic2_txs)
+
+ def test_multisig(self):
+ default = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
+
+ # Contrived case where all the multisig keys are in a single wallet
+ self.log.info("Test migration of a wallet with all keys for a multisig")
+ multisig0 = self.create_legacy_wallet("multisig0")
+ addr1 = multisig0.getnewaddress()
+ addr2 = multisig0.getnewaddress()
+ addr3 = multisig0.getnewaddress()
+
+ ms_info = multisig0.addmultisigaddress(2, [addr1, addr2, addr3])
+
+ multisig0.migratewallet()
+ assert_equal(multisig0.getwalletinfo()["descriptors"], True)
+ self.assert_is_sqlite("multisig0")
+ ms_addr_info = multisig0.getaddressinfo(ms_info["address"])
+ assert_equal(ms_addr_info["ismine"], True)
+ assert_equal(ms_addr_info["desc"], ms_info["descriptor"])
+ assert_equal("multisig0_watchonly" in self.nodes[0].listwallets(), False)
+ assert_equal("multisig0_solvables" in self.nodes[0].listwallets(), False)
+
+ pub1 = multisig0.getaddressinfo(addr1)["pubkey"]
+ pub2 = multisig0.getaddressinfo(addr2)["pubkey"]
+
+ # Some keys in multisig do not belong to this wallet
+ self.log.info("Test migration of a wallet that has some keys in a multisig")
+ self.nodes[0].createwallet(wallet_name="multisig1")
+ multisig1 = self.nodes[0].get_wallet_rpc("multisig1")
+ ms_info = multisig1.addmultisigaddress(2, [multisig1.getnewaddress(), pub1, pub2])
+ ms_info2 = multisig1.addmultisigaddress(2, [multisig1.getnewaddress(), pub1, pub2])
+ assert_equal(multisig1.getwalletinfo()["descriptors"], False)
+
+ addr1 = ms_info["address"]
+ addr2 = ms_info2["address"]
+ txid = default.sendtoaddress(addr1, 10)
+ multisig1.importaddress(addr1)
+ assert_equal(multisig1.getaddressinfo(addr1)["ismine"], False)
+ assert_equal(multisig1.getaddressinfo(addr1)["iswatchonly"], True)
+ assert_equal(multisig1.getaddressinfo(addr1)["solvable"], True)
+ self.generate(self.nodes[0], 1)
+ multisig1.gettransaction(txid)
+ assert_equal(multisig1.getbalances()["watchonly"]["trusted"], 10)
+ assert_equal(multisig1.getaddressinfo(addr2)["ismine"], False)
+ assert_equal(multisig1.getaddressinfo(addr2)["iswatchonly"], False)
+ assert_equal(multisig1.getaddressinfo(addr2)["solvable"], True)
+
+ # Migrating multisig1 should see the multisig is no longer part of multisig1
+ # A new wallet multisig1_watchonly is created which has the multisig address
+ # Transaction to multisig is in multisig1_watchonly and not multisig1
+ multisig1.migratewallet()
+ assert_equal(multisig1.getwalletinfo()["descriptors"], True)
+ self.assert_is_sqlite("multisig1")
+ assert_equal(multisig1.getaddressinfo(addr1)["ismine"], False)
+ assert_equal(multisig1.getaddressinfo(addr1)["iswatchonly"], False)
+ assert_equal(multisig1.getaddressinfo(addr1)["solvable"], False)
+ assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", multisig1.gettransaction, txid)
+ assert_equal(multisig1.getbalance(), 0)
+ assert_equal(multisig1.listtransactions(), [])
+
+ assert_equal("multisig1_watchonly" in self.nodes[0].listwallets(), True)
+ ms1_watchonly = self.nodes[0].get_wallet_rpc("multisig1_watchonly")
+ ms1_wallet_info = ms1_watchonly.getwalletinfo()
+ assert_equal(ms1_wallet_info['descriptors'], True)
+ assert_equal(ms1_wallet_info['private_keys_enabled'], False)
+ self.assert_is_sqlite("multisig1_watchonly")
+ assert_equal(ms1_watchonly.getaddressinfo(addr1)["ismine"], True)
+ assert_equal(ms1_watchonly.getaddressinfo(addr1)["solvable"], True)
+ # Because addr2 was not being watched, it isn't in multisig1_watchonly but rather multisig1_solvables
+ assert_equal(ms1_watchonly.getaddressinfo(addr2)["ismine"], False)
+ assert_equal(ms1_watchonly.getaddressinfo(addr2)["solvable"], False)
+ ms1_watchonly.gettransaction(txid)
+ assert_equal(ms1_watchonly.getbalance(), 10)
+
+ # Migrating multisig1 should see the second multisig is no longer part of multisig1
+ # A new wallet multisig1_solvables is created which has the second address
+ # This should have no transactions
+ assert_equal("multisig1_solvables" in self.nodes[0].listwallets(), True)
+ ms1_solvable = self.nodes[0].get_wallet_rpc("multisig1_solvables")
+ ms1_wallet_info = ms1_solvable.getwalletinfo()
+ assert_equal(ms1_wallet_info['descriptors'], True)
+ assert_equal(ms1_wallet_info['private_keys_enabled'], False)
+ self.assert_is_sqlite("multisig1_solvables")
+ assert_equal(ms1_solvable.getaddressinfo(addr1)["ismine"], False)
+ assert_equal(ms1_solvable.getaddressinfo(addr1)["solvable"], False)
+ assert_equal(ms1_solvable.getaddressinfo(addr2)["ismine"], True)
+ assert_equal(ms1_solvable.getaddressinfo(addr2)["solvable"], True)
+ assert_equal(ms1_solvable.getbalance(), 0)
+ assert_equal(ms1_solvable.listtransactions(), [])
+
+
+ def test_other_watchonly(self):
+ default = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
+
+ # Wallet with an imported address. Should be the same thing as the multisig test
+ self.log.info("Test migration of a wallet with watchonly imports")
+ self.nodes[0].createwallet(wallet_name="imports0")
+ imports0 = self.nodes[0].get_wallet_rpc("imports0")
+ assert_equal(imports0.getwalletinfo()["descriptors"], False)
+
+ # Exteranl address label
+ imports0.setlabel(default.getnewaddress(), "external")
+
+ # Normal non-watchonly tx
+ received_addr = imports0.getnewaddress()
+ imports0.setlabel(received_addr, "Receiving")
+ received_txid = default.sendtoaddress(received_addr, 10)
+
+ # Watchonly tx
+ import_addr = default.getnewaddress()
+ imports0.importaddress(import_addr)
+ imports0.setlabel(import_addr, "imported")
+ received_watchonly_txid = default.sendtoaddress(import_addr, 10)
+
+ # Received watchonly tx that is then spent
+ import_sent_addr = default.getnewaddress()
+ imports0.importaddress(import_sent_addr)
+ received_sent_watchonly_txid = default.sendtoaddress(import_sent_addr, 10)
+ received_sent_watchonly_vout = find_vout_for_address(self.nodes[0], received_sent_watchonly_txid, import_sent_addr)
+ send = default.sendall(recipients=[default.getnewaddress()], options={"inputs": [{"txid": received_sent_watchonly_txid, "vout": received_sent_watchonly_vout}]})
+ sent_watchonly_txid = send["txid"]
+
+ self.generate(self.nodes[0], 1)
+
+ balances = imports0.getbalances()
+ spendable_bal = balances["mine"]["trusted"]
+ watchonly_bal = balances["watchonly"]["trusted"]
+ assert_equal(len(imports0.listtransactions(include_watchonly=True)), 4)
+
+ # Migrate
+ imports0.migratewallet()
+ assert_equal(imports0.getwalletinfo()["descriptors"], True)
+ self.assert_is_sqlite("imports0")
+ assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", imports0.gettransaction, received_watchonly_txid)
+ assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", imports0.gettransaction, received_sent_watchonly_txid)
+ assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", imports0.gettransaction, sent_watchonly_txid)
+ assert_equal(len(imports0.listtransactions(include_watchonly=True)), 1)
+ imports0.gettransaction(received_txid)
+ assert_equal(imports0.getbalance(), spendable_bal)
+
+ assert_equal("imports0_watchonly" in self.nodes[0].listwallets(), True)
+ watchonly = self.nodes[0].get_wallet_rpc("imports0_watchonly")
+ watchonly_info = watchonly.getwalletinfo()
+ assert_equal(watchonly_info["descriptors"], True)
+ self.assert_is_sqlite("imports0_watchonly")
+ assert_equal(watchonly_info["private_keys_enabled"], False)
+ watchonly.gettransaction(received_watchonly_txid)
+ watchonly.gettransaction(received_sent_watchonly_txid)
+ watchonly.gettransaction(sent_watchonly_txid)
+ assert_equal(watchonly.getbalance(), watchonly_bal)
+ assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", watchonly.gettransaction, received_txid)
+ assert_equal(len(watchonly.listtransactions(include_watchonly=True)), 3)
+
+ def test_no_privkeys(self):
+ default = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
+
+ # Migrating an actual watchonly wallet should not create a new watchonly wallet
+ self.log.info("Test migration of a pure watchonly wallet")
+ self.nodes[0].createwallet(wallet_name="watchonly0", disable_private_keys=True)
+ watchonly0 = self.nodes[0].get_wallet_rpc("watchonly0")
+ info = watchonly0.getwalletinfo()
+ assert_equal(info["descriptors"], False)
+ assert_equal(info["private_keys_enabled"], False)
+
+ addr = default.getnewaddress()
+ desc = default.getaddressinfo(addr)["desc"]
+ res = watchonly0.importmulti([
+ {
+ "desc": desc,
+ "watchonly": True,
+ "timestamp": "now",
+ }])
+ assert_equal(res[0]['success'], True)
+ default.sendtoaddress(addr, 10)
+ self.generate(self.nodes[0], 1)
+
+ watchonly0.migratewallet()
+ assert_equal("watchonly0_watchonly" in self.nodes[0].listwallets(), False)
+ info = watchonly0.getwalletinfo()
+ assert_equal(info["descriptors"], True)
+ assert_equal(info["private_keys_enabled"], False)
+ self.assert_is_sqlite("watchonly0")
+
+ # Migrating a wallet with pubkeys added to the keypool
+ self.log.info("Test migration of a pure watchonly wallet with pubkeys in keypool")
+ self.nodes[0].createwallet(wallet_name="watchonly1", disable_private_keys=True)
+ watchonly1 = self.nodes[0].get_wallet_rpc("watchonly1")
+ info = watchonly1.getwalletinfo()
+ assert_equal(info["descriptors"], False)
+ assert_equal(info["private_keys_enabled"], False)
+
+ addr1 = default.getnewaddress(address_type="bech32")
+ addr2 = default.getnewaddress(address_type="bech32")
+ desc1 = default.getaddressinfo(addr1)["desc"]
+ desc2 = default.getaddressinfo(addr2)["desc"]
+ res = watchonly1.importmulti([
+ {
+ "desc": desc1,
+ "keypool": True,
+ "timestamp": "now",
+ },
+ {
+ "desc": desc2,
+ "keypool": True,
+ "timestamp": "now",
+ }
+ ])
+ assert_equal(res[0]["success"], True)
+ assert_equal(res[1]["success"], True)
+ # Before migrating, we can fetch addr1 from the keypool
+ assert_equal(watchonly1.getnewaddress(address_type="bech32"), addr1)
+
+ watchonly1.migratewallet()
+ info = watchonly1.getwalletinfo()
+ assert_equal(info["descriptors"], True)
+ assert_equal(info["private_keys_enabled"], False)
+ self.assert_is_sqlite("watchonly1")
+ # After migrating, the "keypool" is empty
+ assert_raises_rpc_error(-4, "Error: This wallet has no available keys", watchonly1.getnewaddress)
+
+ def test_pk_coinbases(self):
+ self.log.info("Test migration of a wallet using old pk() coinbases")
+ wallet = self.create_legacy_wallet("pkcb")
+
+ addr = wallet.getnewaddress()
+ addr_info = wallet.getaddressinfo(addr)
+ desc = descsum_create("pk(" + addr_info["pubkey"] + ")")
+
+ self.nodes[0].generatetodescriptor(1, desc, invalid_call=False)
+
+ bals = wallet.getbalances()
+
+ wallet.migratewallet()
+
+ assert_equal(bals, wallet.getbalances())
+
+ def test_encrypted(self):
+ self.log.info("Test migration of an encrypted wallet")
+ wallet = self.create_legacy_wallet("encrypted")
+
+ wallet.encryptwallet("pass")
+
+ assert_raises_rpc_error(-15, "Error: migratewallet on encrypted wallets is currently unsupported.", wallet.migratewallet)
+ # TODO: Fix migratewallet so that we can actually migrate encrypted wallets
+
+ def run_test(self):
+ self.generate(self.nodes[0], 101)
+
+ # TODO: Test the actual records in the wallet for these tests too. The behavior may be correct, but the data written may not be what we actually want
+ self.test_basic()
+ self.test_multisig()
+ self.test_other_watchonly()
+ self.test_no_privkeys()
+ self.test_pk_coinbases()
+ self.test_encrypted()
+
+if __name__ == '__main__':
+ WalletMigrationTest().main()
diff --git a/test/functional/wallet_miniscript.py b/test/functional/wallet_miniscript.py
new file mode 100755
index 0000000000..2252f1e424
--- /dev/null
+++ b/test/functional/wallet_miniscript.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test Miniscript descriptors integration in the wallet."""
+
+from test_framework.descriptors import descsum_create
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+
+MINISCRIPTS = [
+ # One of two keys
+ "or_b(pk(tpubD6NzVbkrYhZ4XRMcMFMMFvzVt6jaDAtjZhD7JLwdPdMm9xa76DnxYYP7w9TZGJDVFkek3ArwVsuacheqqPog8TH5iBCX1wuig8PLXim4n9a/*),s:pk(tpubD6NzVbkrYhZ4WsqRzDmkL82SWcu42JzUvKWzrJHQ8EC2vEHRHkXj1De93sD3biLrKd8XGnamXURGjMbYavbszVDXpjXV2cGUERucLJkE6cy/*))",
+ # A script similar (same spending policy) to BOLT3's offered HTLC (with anchor outputs)
+ "or_d(pk(tpubD6NzVbkrYhZ4XRMcMFMMFvzVt6jaDAtjZhD7JLwdPdMm9xa76DnxYYP7w9TZGJDVFkek3ArwVsuacheqqPog8TH5iBCX1wuig8PLXim4n9a/*),and_v(and_v(v:pk(tpubD6NzVbkrYhZ4WsqRzDmkL82SWcu42JzUvKWzrJHQ8EC2vEHRHkXj1De93sD3biLrKd8XGnamXURGjMbYavbszVDXpjXV2cGUERucLJkE6cy/*),or_c(pk(tpubD6NzVbkrYhZ4YNwtTWrKRJQzQX3PjPKeUQg1gYh1hiLMkk1cw8SRLgB1yb7JzE8bHKNt6EcZXkJ6AqpCZL1aaRSjnG36mLgbQvJZBNsjWnG/*),v:hash160(7f999c905d5e35cefd0a37673f746eb13fba3640))),older(1)))",
+ # A Revault Unvault policy with the older() replaced by an after()
+ "andor(multi(2,tpubD6NzVbkrYhZ4YMQC15JS7QcrsAyfGrGiykweqMmPxTkEVScu7vCZLNpPXW1XphHwzsgmqdHWDQAfucbM72EEB1ZEyfgZxYvkZjYVXx1xS9p/*,tpubD6NzVbkrYhZ4WkCyc7E3z6g6NkypHMiecnwc4DpWHTPqFdteRGkEKukdrSSyJGNnGrHNMfy4BCw2UXo5soYRCtCDDfy4q8pc8oyB7RgTFv8/*),and_v(v:multi(4,030f64b922aee2fd597f104bc6cb3b670f1ca2c6c49b1071a1a6c010575d94fe5a,02abe475b199ec3d62fa576faee16a334fdb86ffb26dce75becebaaedf328ac3fe,0314f3dc33595b0d016bb522f6fe3a67680723d842c1b9b8ae6b59fdd8ab5cccb4,025eba3305bd3c829e4e1551aac7358e4178832c739e4fc4729effe428de0398ab),after(424242)),thresh(4,pkh(tpubD6NzVbkrYhZ4YVrNggiT2ptVHwnFbLBqDkCtV5HkxR4WtcRLAQReKTkqZGNcV6GE7cQsmpBzzSzhk16DUwB1gn1L7ZPnJF2dnNePP1uMBCY/*),a:pkh(tpubD6NzVbkrYhZ4YU9vM1s53UhD75UyJatx8EMzMZ3VUjR2FciNfLLkAw6a4pWACChzobTseNqdWk4G7ZdBqRDLtLSACKykTScmqibb1ZrCvJu/*),a:pkh(tpubD6NzVbkrYhZ4YUHcFfuH9iEBLiH8CBRJTpS7X3qjHmh82m1KCNbzs6w9gyK8oWHSZmKHWcakAXCGfbKg6xoCvKzQCWAHyxaC7QcWfmzyBf4/*),a:pkh(tpubD6NzVbkrYhZ4XXEmQtS3sgxpJbMyMg4McqRR1Af6ULzyrTRnhwjyr1etPD7svap9oFtJf4MM72brUb5o7uvF2Jyszc5c1t836fJW7SX2e8D/*)))",
+ # Liquid-like federated pegin with emergency recovery keys
+ "or_i(and_b(pk(029ffbe722b147f3035c87cb1c60b9a5947dd49c774cc31e94773478711a929ac0),a:and_b(pk(025f05815e3a1a8a83bfbb03ce016c9a2ee31066b98f567f6227df1d76ec4bd143),a:and_b(pk(025625f41e4a065efc06d5019cbbd56fe8c07595af1231e7cbc03fafb87ebb71ec),a:and_b(pk(02a27c8b850a00f67da3499b60562673dcf5fdfb82b7e17652a7ac54416812aefd),s:pk(03e618ec5f384d6e19ca9ebdb8e2119e5bef978285076828ce054e55c4daf473e2))))),and_v(v:thresh(2,pkh(tpubD6NzVbkrYhZ4YK67cd5fDe4fBVmGB2waTDrAt1q4ey9HPq9veHjWkw3VpbaCHCcWozjkhgAkWpFrxuPMUrmXVrLHMfEJ9auoZA6AS1g3grC/*),a:pkh(033841045a531e1adf9910a6ec279589a90b3b8a904ee64ffd692bd08a8996c1aa),a:pkh(02aebf2d10b040eb936a6f02f44ee82f8b34f5c1ccb20ff3949c2b28206b7c1068)),older(4209713)))",
+]
+
+
+class WalletMiniscriptTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+ self.skip_if_no_sqlite()
+
+ def watchonly_test(self, ms):
+ self.log.info(f"Importing Miniscript '{ms}'")
+ desc = descsum_create(f"wsh({ms})")
+ assert self.ms_wo_wallet.importdescriptors(
+ [
+ {
+ "desc": desc,
+ "active": True,
+ "range": 2,
+ "next_index": 0,
+ "timestamp": "now",
+ }
+ ]
+ )[0]["success"]
+
+ self.log.info("Testing we derive new addresses for it")
+ assert_equal(
+ self.ms_wo_wallet.getnewaddress(), self.funder.deriveaddresses(desc, 0)[0]
+ )
+ assert_equal(
+ self.ms_wo_wallet.getnewaddress(), self.funder.deriveaddresses(desc, 1)[1]
+ )
+
+ self.log.info("Testing we detect funds sent to one of them")
+ addr = self.ms_wo_wallet.getnewaddress()
+ txid = self.funder.sendtoaddress(addr, 0.01)
+ self.wait_until(
+ lambda: len(self.ms_wo_wallet.listunspent(minconf=0, addresses=[addr])) == 1
+ )
+ utxo = self.ms_wo_wallet.listunspent(minconf=0, addresses=[addr])[0]
+ assert utxo["txid"] == txid and not utxo["solvable"] # No satisfaction logic (yet)
+
+ def run_test(self):
+ self.log.info("Making a descriptor wallet")
+ self.funder = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
+ self.nodes[0].createwallet(
+ wallet_name="ms_wo", descriptors=True, disable_private_keys=True
+ )
+ self.ms_wo_wallet = self.nodes[0].get_wallet_rpc("ms_wo")
+
+ # Sanity check we wouldn't let an insane Miniscript descriptor in
+ res = self.ms_wo_wallet.importdescriptors(
+ [
+ {
+ "desc": descsum_create(
+ "wsh(and_b(ripemd160(1fd9b55a054a2b3f658d97e6b84cf3ee00be429a),a:1))"
+ ),
+ "active": False,
+ "timestamp": "now",
+ }
+ ]
+ )[0]
+ assert not res["success"]
+ assert "is not sane: witnesses without signature exist" in res["error"]["message"]
+
+ # Test we can track any type of Miniscript
+ for ms in MINISCRIPTS:
+ self.watchonly_test(ms)
+
+
+if __name__ == "__main__":
+ WalletMiniscriptTest().main()
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index dcb82bbbe9..99e472a7b4 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -356,7 +356,7 @@ class MultiWalletTest(BitcoinTestFramework):
self.log.info("Test dynamic wallet unloading")
# Test `unloadwallet` errors
- assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].unloadwallet)
+ assert_raises_rpc_error(-1, "JSON value of type null is not of expected type string", self.nodes[0].unloadwallet)
assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", self.nodes[0].unloadwallet, "dummy")
assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", node.get_wallet_rpc("dummy").unloadwallet)
assert_raises_rpc_error(-8, "RPC endpoint wallet and wallet_name parameter specify different wallets", w1.unloadwallet, "w2"),
diff --git a/test/functional/wallet_resendwallettransactions.py b/test/functional/wallet_resendwallettransactions.py
index 6552bfe60c..b3d02fbfc9 100755
--- a/test/functional/wallet_resendwallettransactions.py
+++ b/test/functional/wallet_resendwallettransactions.py
@@ -9,10 +9,13 @@ from test_framework.blocktools import (
create_block,
create_coinbase,
)
+from test_framework.messages import DEFAULT_MEMPOOL_EXPIRY_HOURS
from test_framework.p2p import P2PTxInvStore
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal
-
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
class ResendWalletTransactionsTest(BitcoinTestFramework):
def set_test_params(self):
@@ -27,13 +30,9 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
peer_first = node.add_p2p_connection(P2PTxInvStore())
self.log.info("Create a new transaction and wait until it's broadcast")
- txid = node.sendtoaddress(node.getnewaddress(), 1)
-
- # Wallet rebroadcast is first scheduled 1 sec after startup (see
- # nNextResend in ResendWalletTransactions()). Tell scheduler to call
- # MaybeResendWalletTxn now to initialize nNextResend before the first
- # setmocktime call below.
- node.mockscheduler(1)
+ parent_utxo, indep_utxo = node.listunspent()[:2]
+ addr = node.getnewaddress()
+ txid = node.send(outputs=[{addr: 1}], options={"inputs": [parent_utxo]})["txid"]
# Can take a few seconds due to transaction trickling
peer_first.wait_for_broadcast([txid])
@@ -51,7 +50,7 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
block.solve()
node.submitblock(block.serialize().hex())
- # Set correct m_best_block_time, which is used in ResendWalletTransactions
+ # Set correct m_best_block_time, which is used in ResubmitWalletTransactions
node.syncwithvalidationinterfacequeue()
now = int(time.time())
@@ -60,20 +59,67 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
twelve_hrs = 12 * 60 * 60
two_min = 2 * 60
node.setmocktime(now + twelve_hrs - two_min)
- node.mockscheduler(1) # Tell scheduler to call MaybeResendWalletTxn now
+ node.mockscheduler(60) # Tell scheduler to call MaybeResendWalletTxs now
assert_equal(int(txid, 16) in peer_second.get_invs(), False)
self.log.info("Bump time & check that transaction is rebroadcast")
# Transaction should be rebroadcast approximately 24 hours in the future,
# but can range from 12-36. So bump 36 hours to be sure.
- with node.assert_debug_log(['ResendWalletTransactions: resubmit 1 unconfirmed transactions']):
+ with node.assert_debug_log(['resubmit 1 unconfirmed transactions']):
node.setmocktime(now + 36 * 60 * 60)
- # Tell scheduler to call MaybeResendWalletTxn now.
- node.mockscheduler(1)
+ # Tell scheduler to call MaybeResendWalletTxs now.
+ node.mockscheduler(60)
# Give some time for trickle to occur
node.setmocktime(now + 36 * 60 * 60 + 600)
peer_second.wait_for_broadcast([txid])
+ self.log.info("Chain of unconfirmed not-in-mempool txs are rebroadcast")
+ # This tests that the node broadcasts the parent transaction before the child transaction.
+ # To test that scenario, we need a method to reliably get a child transaction placed
+ # in mapWallet positioned before the parent. We cannot predict the position in mapWallet,
+ # but we can observe it using listreceivedbyaddress and other related RPCs.
+ #
+ # So we will create the child transaction, use listreceivedbyaddress to see what the
+ # ordering of mapWallet is, if the child is not before the parent, we will create a new
+ # child (via bumpfee) and remove the old child (via removeprunedfunds) until we get the
+ # ordering of child before parent.
+ child_txid = node.send(outputs=[{addr: 0.5}], options={"inputs": [{"txid":txid, "vout":0}]})["txid"]
+ while True:
+ txids = node.listreceivedbyaddress(minconf=0, address_filter=addr)[0]["txids"]
+ if txids == [child_txid, txid]:
+ break
+ bumped = node.bumpfee(child_txid)
+ # The scheduler queue creates a copy of the added tx after
+ # send/bumpfee and re-adds it to the wallet (undoing the next
+ # removeprunedfunds). So empty the scheduler queue:
+ node.syncwithvalidationinterfacequeue()
+ node.removeprunedfunds(child_txid)
+ child_txid = bumped["txid"]
+ entry_time = node.getmempoolentry(child_txid)["time"]
+
+ block_time = entry_time + 6 * 60
+ node.setmocktime(block_time)
+ block = create_block(int(node.getbestblockhash(), 16), create_coinbase(node.getblockcount() + 1), block_time)
+ block.solve()
+ node.submitblock(block.serialize().hex())
+ # Set correct m_best_block_time, which is used in ResubmitWalletTransactions
+ node.syncwithvalidationinterfacequeue()
+
+ # Evict these txs from the mempool
+ evict_time = block_time + 60 * 60 * DEFAULT_MEMPOOL_EXPIRY_HOURS + 5
+ node.setmocktime(evict_time)
+ indep_send = node.send(outputs=[{node.getnewaddress(): 1}], options={"inputs": [indep_utxo]})
+ node.getmempoolentry(indep_send["txid"])
+ assert_raises_rpc_error(-5, "Transaction not in mempool", node.getmempoolentry, txid)
+ assert_raises_rpc_error(-5, "Transaction not in mempool", node.getmempoolentry, child_txid)
+
+ # Rebroadcast and check that parent and child are both in the mempool
+ with node.assert_debug_log(['resubmit 2 unconfirmed transactions']):
+ node.setmocktime(evict_time + 36 * 60 * 60) # 36 hrs is the upper limit of the resend timer
+ node.mockscheduler(60)
+ node.getmempoolentry(txid)
+ node.getmempoolentry(child_txid)
+
if __name__ == '__main__':
ResendWalletTransactionsTest().main()
diff --git a/test/functional/wallet_sendall.py b/test/functional/wallet_sendall.py
index aa8d2a9d2c..4fe11455b1 100755
--- a/test/functional/wallet_sendall.py
+++ b/test/functional/wallet_sendall.py
@@ -221,6 +221,11 @@ class SendallTest(BitcoinTestFramework):
self.add_utxos([16, 5])
spent_utxo = self.wallet.listunspent()[0]
+ # fails on out of bounds vout
+ assert_raises_rpc_error(-8,
+ "Input not found. UTXO ({}:{}) is not part of wallet.".format(spent_utxo["txid"], 1000),
+ self.wallet.sendall, recipients=[self.remainder_target], options={"inputs": [{"txid": spent_utxo["txid"], "vout": 1000}]})
+
# fails on unconfirmed spent UTXO
self.wallet.sendall(recipients=[self.remainder_target])
assert_raises_rpc_error(-8,
@@ -264,6 +269,59 @@ class SendallTest(BitcoinTestFramework):
recipients=[self.remainder_target],
options={"inputs": [utxo], "send_max": True})
+ @cleanup
+ def sendall_fails_on_high_fee(self):
+ self.log.info("Test sendall fails if the transaction fee exceeds the maxtxfee")
+ self.add_utxos([21])
+
+ assert_raises_rpc_error(
+ -4,
+ "Fee exceeds maximum configured by user",
+ self.wallet.sendall,
+ recipients=[self.remainder_target],
+ fee_rate=100000)
+
+ @cleanup
+ def sendall_watchonly_specific_inputs(self):
+ self.log.info("Test sendall with a subset of UTXO pool in a watchonly wallet")
+ self.add_utxos([17, 4])
+ utxo = self.wallet.listunspent()[0]
+
+ self.nodes[0].createwallet(wallet_name="watching", disable_private_keys=True)
+ watchonly = self.nodes[0].get_wallet_rpc("watching")
+
+ import_req = [{
+ "desc": utxo["desc"],
+ "timestamp": 0,
+ }]
+ if self.options.descriptors:
+ watchonly.importdescriptors(import_req)
+ else:
+ watchonly.importmulti(import_req)
+
+ sendall_tx_receipt = watchonly.sendall(recipients=[self.remainder_target], options={"inputs": [utxo]})
+ psbt = sendall_tx_receipt["psbt"]
+ decoded = self.nodes[0].decodepsbt(psbt)
+ assert_equal(len(decoded["inputs"]), 1)
+ assert_equal(len(decoded["outputs"]), 1)
+ assert_equal(decoded["tx"]["vin"][0]["txid"], utxo["txid"])
+ assert_equal(decoded["tx"]["vin"][0]["vout"], utxo["vout"])
+ assert_equal(decoded["tx"]["vout"][0]["scriptPubKey"]["address"], self.remainder_target)
+
+ # This tests needs to be the last one otherwise @cleanup will fail with "Transaction too large" error
+ def sendall_fails_with_transaction_too_large(self):
+ self.log.info("Test that sendall fails if resulting transaction is too large")
+ # create many inputs
+ outputs = {self.wallet.getnewaddress(): 0.000025 for _ in range(1600)}
+ self.def_wallet.sendmany(amounts=outputs)
+ self.generate(self.nodes[0], 1)
+
+ assert_raises_rpc_error(
+ -4,
+ "Transaction too large.",
+ self.wallet.sendall,
+ recipients=[self.remainder_target])
+
def run_test(self):
self.nodes[0].createwallet("activewallet")
self.wallet = self.nodes[0].get_wallet_rpc("activewallet")
@@ -312,5 +370,14 @@ class SendallTest(BitcoinTestFramework):
# Sendall fails when using send_max while specifying inputs
self.sendall_fails_on_specific_inputs_with_send_max()
+ # Sendall fails when providing a fee that is too high
+ self.sendall_fails_on_high_fee()
+
+ # Sendall succeeds with watchonly wallets spending specific UTXOs
+ self.sendall_watchonly_specific_inputs()
+
+ # Sendall fails when many inputs result to too large transaction
+ self.sendall_fails_with_transaction_too_large()
+
if __name__ == '__main__':
SendallTest().main()
diff --git a/test/functional/wallet_signer.py b/test/functional/wallet_signer.py
index 8e4e1f5d36..5609ac9bf5 100755
--- a/test/functional/wallet_signer.py
+++ b/test/functional/wallet_signer.py
@@ -32,6 +32,13 @@ class WalletSignerTest(BitcoinTestFramework):
else:
return path
+ def mock_multi_signers_path(self):
+ path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mocks', 'multi_signers.py')
+ if platform.system() == "Windows":
+ return "py " + path
+ else:
+ return path
+
def set_test_params(self):
self.num_nodes = 2
# The experimental syscall sandbox feature (-sandbox) is not compatible with -signer (which
@@ -58,6 +65,8 @@ class WalletSignerTest(BitcoinTestFramework):
self.test_valid_signer()
self.restart_node(1, [f"-signer={self.mock_invalid_signer_path()}", "-keypool=10"])
self.test_invalid_signer()
+ self.restart_node(1, [f"-signer={self.mock_multi_signers_path()}", "-keypool=10"])
+ self.test_multiple_signers()
def test_valid_signer(self):
self.log.debug(f"-signer={self.mock_signer_path()}")
@@ -212,5 +221,11 @@ class WalletSignerTest(BitcoinTestFramework):
self.log.info('Test invalid external signer')
assert_raises_rpc_error(-1, "Invalid descriptor", self.nodes[1].createwallet, wallet_name='hww_invalid', disable_private_keys=True, descriptors=True, external_signer=True)
+ def test_multiple_signers(self):
+ self.log.debug(f"-signer={self.mock_multi_signers_path()}")
+ self.log.info('Test multiple external signers')
+
+ assert_raises_rpc_error(-1, "GetExternalSigner: More than one external signer found", self.nodes[1].createwallet, wallet_name='multi_hww', disable_private_keys=True, descriptors=True, external_signer=True)
+
if __name__ == '__main__':
WalletSignerTest().main()
diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/wallet_signrawtransactionwithwallet.py
index 8da2cfa72b..6b30386b7e 100755
--- a/test/functional/rpc_signrawtransaction.py
+++ b/test/functional/wallet_signrawtransactionwithwallet.py
@@ -2,16 +2,14 @@
# Copyright (c) 2015-2021 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test transaction signing using the signrawtransaction* RPCs."""
+"""Test transaction signing using the signrawtransactionwithwallet RPC."""
from test_framework.blocktools import (
COINBASE_MATURITY,
)
from test_framework.address import (
- script_to_p2sh,
script_to_p2wsh,
)
-from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
@@ -29,20 +27,13 @@ from test_framework.script import (
OP_DROP,
OP_TRUE,
)
-from test_framework.script_util import (
- key_to_p2pk_script,
- key_to_p2pkh_script,
- script_to_p2sh_p2wsh_script,
- script_to_p2wsh_script,
-)
-from test_framework.wallet_util import bytes_to_wif
from decimal import (
Decimal,
getcontext,
)
-class SignRawTransactionsTest(BitcoinTestFramework):
+class SignRawTransactionWithWalletTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
@@ -50,35 +41,6 @@ class SignRawTransactionsTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- def successful_signing_test(self):
- """Create and sign a valid raw transaction with one input.
-
- Expected results:
-
- 1) The transaction has a complete set of signatures
- 2) No script verification error occurred"""
- self.log.info("Test valid raw transaction with one input")
- privKeys = ['cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N', 'cVKpPfVKSJxKqVpE9awvXNWuLHCa5j5tiE7K6zbUSptFpTEtiFrA']
-
- inputs = [
- # Valid pay-to-pubkey scripts
- {'txid': '9b907ef1e3c26fc71fe4a4b3580bc75264112f95050014157059c736f0202e71', 'vout': 0,
- 'scriptPubKey': '76a91460baa0f494b38ce3c940dea67f3804dc52d1fb9488ac'},
- {'txid': '83a4f6a6b73660e13ee6cb3c6063fa3759c50c9b7521d0536022961898f4fb02', 'vout': 0,
- 'scriptPubKey': '76a914669b857c03a5ed269d5d85a1ffac9ed5d663072788ac'},
- ]
-
- outputs = {'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB': 0.1}
-
- rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
- rawTxSigned = self.nodes[0].signrawtransactionwithkey(rawTx, privKeys, inputs)
-
- # 1) The transaction has a complete set of signatures
- assert rawTxSigned['complete']
-
- # 2) No script verification error occurred
- assert 'errors' not in rawTxSigned
-
def test_with_lock_outputs(self):
self.log.info("Test correct error reporting when trying to sign a locked output")
self.nodes[0].encryptwallet("password")
@@ -191,60 +153,6 @@ class SignRawTransactionsTest(BitcoinTestFramework):
assert_equal(signedtx["hex"], signedtx2["hex"])
self.nodes[0].walletlock()
- def witness_script_test(self):
- self.log.info("Test signing transaction to P2SH-P2WSH addresses without wallet")
- # Create a new P2SH-P2WSH 1-of-1 multisig address:
- eckey = ECKey()
- eckey.generate()
- embedded_privkey = bytes_to_wif(eckey.get_bytes())
- embedded_pubkey = eckey.get_pubkey().get_bytes().hex()
- p2sh_p2wsh_address = self.nodes[1].createmultisig(1, [embedded_pubkey], "p2sh-segwit")
- # send transaction to P2SH-P2WSH 1-of-1 multisig address
- self.generate(self.nodes[0], COINBASE_MATURITY + 1)
- self.nodes[0].sendtoaddress(p2sh_p2wsh_address["address"], 49.999)
- self.generate(self.nodes[0], 1)
- # Get the UTXO info from scantxoutset
- unspent_output = self.nodes[1].scantxoutset('start', [p2sh_p2wsh_address['descriptor']])['unspents'][0]
- spk = script_to_p2sh_p2wsh_script(p2sh_p2wsh_address['redeemScript']).hex()
- unspent_output['witnessScript'] = p2sh_p2wsh_address['redeemScript']
- unspent_output['redeemScript'] = script_to_p2wsh_script(unspent_output['witnessScript']).hex()
- assert_equal(spk, unspent_output['scriptPubKey'])
- # Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys
- spending_tx = self.nodes[0].createrawtransaction([unspent_output], {self.nodes[1].get_wallet_rpc(self.default_wallet_name).getnewaddress(): Decimal("49.998")})
- spending_tx_signed = self.nodes[0].signrawtransactionwithkey(spending_tx, [embedded_privkey], [unspent_output])
- # Check the signing completed successfully
- assert 'complete' in spending_tx_signed
- assert_equal(spending_tx_signed['complete'], True)
-
- # Now test with P2PKH and P2PK scripts as the witnessScript
- for tx_type in ['P2PKH', 'P2PK']: # these tests are order-independent
- self.verify_txn_with_witness_script(tx_type)
-
- def verify_txn_with_witness_script(self, tx_type):
- self.log.info("Test with a {} script as the witnessScript".format(tx_type))
- eckey = ECKey()
- eckey.generate()
- embedded_privkey = bytes_to_wif(eckey.get_bytes())
- embedded_pubkey = eckey.get_pubkey().get_bytes().hex()
- witness_script = {
- 'P2PKH': key_to_p2pkh_script(embedded_pubkey).hex(),
- 'P2PK': key_to_p2pk_script(embedded_pubkey).hex()
- }.get(tx_type, "Invalid tx_type")
- redeem_script = script_to_p2wsh_script(witness_script).hex()
- addr = script_to_p2sh(redeem_script)
- script_pub_key = self.nodes[1].validateaddress(addr)['scriptPubKey']
- # Fund that address
- txid = self.nodes[0].sendtoaddress(addr, 10)
- vout = find_vout_for_address(self.nodes[0], txid, addr)
- self.generate(self.nodes[0], 1)
- # Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys
- spending_tx = self.nodes[0].createrawtransaction([{'txid': txid, 'vout': vout}], {self.nodes[1].getnewaddress(): Decimal("9.999")})
- spending_tx_signed = self.nodes[0].signrawtransactionwithkey(spending_tx, [embedded_privkey], [{'txid': txid, 'vout': vout, 'scriptPubKey': script_pub_key, 'redeemScript': redeem_script, 'witnessScript': witness_script, 'amount': 10}])
- # Check the signing completed successfully
- assert 'complete' in spending_tx_signed
- assert_equal(spending_tx_signed['complete'], True)
- self.nodes[0].sendrawtransaction(spending_tx_signed['hex'])
-
def OP_1NEGATE_test(self):
self.log.info("Test OP_1NEGATE (0x4f) satisfies BIP62 minimal push standardness rule")
hex_str = (
@@ -385,9 +293,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
])
def run_test(self):
- self.successful_signing_test()
self.script_verification_error_test()
- self.witness_script_test()
self.OP_1NEGATE_test()
self.test_with_lock_outputs()
self.test_fully_signed_tx()
@@ -397,4 +303,4 @@ class SignRawTransactionsTest(BitcoinTestFramework):
if __name__ == '__main__':
- SignRawTransactionsTest().main()
+ SignRawTransactionWithWalletTest().main()
diff --git a/test/functional/wallet_simulaterawtx.py b/test/functional/wallet_simulaterawtx.py
new file mode 100755
index 0000000000..a408b99515
--- /dev/null
+++ b/test/functional/wallet_simulaterawtx.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python3
+# Copyright (c) 2021 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test simulaterawtransaction.
+"""
+
+from decimal import Decimal
+from test_framework.blocktools import COINBASE_MATURITY
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_approx,
+ assert_equal,
+ assert_raises_rpc_error,
+)
+
+class SimulateTxTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def setup_network(self, split=False):
+ self.setup_nodes()
+
+ def run_test(self):
+ node = self.nodes[0]
+
+ self.generate(node, 1, sync_fun=self.no_op) # Leave IBD
+
+ node.createwallet(wallet_name='w0')
+ node.createwallet(wallet_name='w1')
+ node.createwallet(wallet_name='w2', disable_private_keys=True)
+ w0 = node.get_wallet_rpc('w0')
+ w1 = node.get_wallet_rpc('w1')
+ w2 = node.get_wallet_rpc('w2')
+
+ self.generatetoaddress(node, COINBASE_MATURITY + 1, w0.getnewaddress())
+ assert_equal(w0.getbalance(), 50.0)
+ assert_equal(w1.getbalance(), 0.0)
+
+ address1 = w1.getnewaddress()
+ address2 = w1.getnewaddress()
+
+ # Add address1 as watch-only to w2
+ w2.importpubkey(pubkey=w1.getaddressinfo(address1)["pubkey"])
+
+ tx1 = node.createrawtransaction([], [{address1: 5.0}])
+ tx2 = node.createrawtransaction([], [{address2: 10.0}])
+
+ # w0 should be unaffected, w2 should see +5 for tx1
+ assert_equal(w0.simulaterawtransaction([tx1])["balance_change"], 0.0)
+ assert_equal(w2.simulaterawtransaction([tx1])["balance_change"], 5.0)
+
+ # w1 should see +5 balance for tx1
+ assert_equal(w1.simulaterawtransaction([tx1])["balance_change"], 5.0)
+
+ # w0 should be unaffected, w2 should see +5 for both transactions
+ assert_equal(w0.simulaterawtransaction([tx1, tx2])["balance_change"], 0.0)
+ assert_equal(w2.simulaterawtransaction([tx1, tx2])["balance_change"], 5.0)
+
+ # w1 should see +15 balance for both transactions
+ assert_equal(w1.simulaterawtransaction([tx1, tx2])["balance_change"], 15.0)
+
+ # w0 funds transaction; it should now see a decrease in (tx fee and payment), and w1 should see the same as above
+ funding = w0.fundrawtransaction(tx1)
+ tx1 = funding["hex"]
+ tx1changepos = funding["changepos"]
+ bitcoin_fee = Decimal(funding["fee"])
+
+ # w0 sees fee + 5 btc decrease, w2 sees + 5 btc
+ assert_approx(w0.simulaterawtransaction([tx1])["balance_change"], -(Decimal("5") + bitcoin_fee))
+ assert_approx(w2.simulaterawtransaction([tx1])["balance_change"], Decimal("5"))
+
+ # w1 sees same as before
+ assert_equal(w1.simulaterawtransaction([tx1])["balance_change"], 5.0)
+
+ # same inputs (tx) more than once should error
+ assert_raises_rpc_error(-8, "Transaction(s) are spending the same output more than once", w0.simulaterawtransaction, [tx1,tx1])
+
+ tx1ob = node.decoderawtransaction(tx1)
+ tx1hex = tx1ob["txid"]
+ tx1vout = 1 - tx1changepos
+ # tx3 spends new w1 UTXO paying to w0
+ tx3 = node.createrawtransaction([{"txid": tx1hex, "vout": tx1vout}], {w0.getnewaddress(): 4.9999})
+ # tx4 spends new w1 UTXO paying to w1
+ tx4 = node.createrawtransaction([{"txid": tx1hex, "vout": tx1vout}], {w1.getnewaddress(): 4.9999})
+
+ # on their own, both should fail due to missing input(s)
+ assert_raises_rpc_error(-8, "One or more transaction inputs are missing or have been spent already", w0.simulaterawtransaction, [tx3])
+ assert_raises_rpc_error(-8, "One or more transaction inputs are missing or have been spent already", w1.simulaterawtransaction, [tx3])
+ assert_raises_rpc_error(-8, "One or more transaction inputs are missing or have been spent already", w0.simulaterawtransaction, [tx4])
+ assert_raises_rpc_error(-8, "One or more transaction inputs are missing or have been spent already", w1.simulaterawtransaction, [tx4])
+
+ # they should succeed when including tx1:
+ # wallet tx3 tx4
+ # w0 -5 - bitcoin_fee + 4.9999 -5 - bitcoin_fee
+ # w1 0 +4.9999
+ assert_approx(w0.simulaterawtransaction([tx1, tx3])["balance_change"], -Decimal("5") - bitcoin_fee + Decimal("4.9999"))
+ assert_approx(w1.simulaterawtransaction([tx1, tx3])["balance_change"], 0)
+ assert_approx(w0.simulaterawtransaction([tx1, tx4])["balance_change"], -Decimal("5") - bitcoin_fee)
+ assert_approx(w1.simulaterawtransaction([tx1, tx4])["balance_change"], Decimal("4.9999"))
+
+ # they should fail if attempting to include both tx3 and tx4
+ assert_raises_rpc_error(-8, "Transaction(s) are spending the same output more than once", w0.simulaterawtransaction, [tx1, tx3, tx4])
+ assert_raises_rpc_error(-8, "Transaction(s) are spending the same output more than once", w1.simulaterawtransaction, [tx1, tx3, tx4])
+
+ # send tx1 to avoid reusing same UTXO below
+ node.sendrawtransaction(w0.signrawtransactionwithwallet(tx1)["hex"])
+ self.generate(node, 1, sync_fun=self.no_op) # Confirm tx to trigger error below
+ self.sync_all()
+
+ # w0 funds transaction 2; it should now see a decrease in (tx fee and payment), and w1 should see the same as above
+ funding = w0.fundrawtransaction(tx2)
+ tx2 = funding["hex"]
+ bitcoin_fee2 = Decimal(funding["fee"])
+ assert_approx(w0.simulaterawtransaction([tx2])["balance_change"], -(Decimal("10") + bitcoin_fee2))
+ assert_approx(w1.simulaterawtransaction([tx2])["balance_change"], +(Decimal("10")))
+ assert_approx(w2.simulaterawtransaction([tx2])["balance_change"], 0)
+
+ # w0-w2 error due to tx1 already being mined
+ assert_raises_rpc_error(-8, "One or more transaction inputs are missing or have been spent already", w0.simulaterawtransaction, [tx1, tx2])
+ assert_raises_rpc_error(-8, "One or more transaction inputs are missing or have been spent already", w1.simulaterawtransaction, [tx1, tx2])
+ assert_raises_rpc_error(-8, "One or more transaction inputs are missing or have been spent already", w2.simulaterawtransaction, [tx1, tx2])
+
+if __name__ == '__main__':
+ SimulateTxTest().main()
diff --git a/test/functional/wallet_taproot.py b/test/functional/wallet_taproot.py
index d238c50bca..c2acafb373 100755
--- a/test/functional/wallet_taproot.py
+++ b/test/functional/wallet_taproot.py
@@ -5,9 +5,11 @@
"""Test generation and spending of P2TR addresses."""
import random
+import uuid
from decimal import Decimal
from test_framework.address import output_key_to_p2tr
+from test_framework.key import H_POINT
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
from test_framework.descriptors import descsum_create
@@ -19,6 +21,7 @@ from test_framework.script import (
OP_NUMEQUAL,
taproot_construct,
)
+from test_framework.segwit_addr import encode_segwit_address
# xprvs/xpubs, and m/* derived x-only pubkeys (created using independent implementation)
KEYS = [
@@ -157,9 +160,6 @@ KEYS = [
CHANGE_XPRV = "tprv8ZgxMBicQKsPcyDrWwiecVnTtFmfRwbfFqEfR4ZGWvq5aTTwLBWmAm5zrbMcYtb9gQNFfhRfqhhrBG37U3nhmXxEgeEPBJGHAPrHCrAd1WX"
CHANGE_XPUB = "tpubD6NzVbkrYhZ4WSFeQbPF1uSaTHHbbGnZq8qShabZwCdUQwihxaLMMFhs2kidGF2qrRKiQVqw8VoyuTHj1bZqmMXMeciaU1gBjWA1sim2zUB"
-# Point with no known discrete log.
-H_POINT = "50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0"
-
def key(hex_key):
"""Construct an x-only pubkey from its hex representation."""
@@ -184,6 +184,9 @@ def compute_taproot_address(pubkey, scripts):
"""Compute the address for a taproot output with given inner key and scripts."""
return output_key_to_p2tr(taproot_construct(pubkey, scripts).output_pubkey)
+def compute_raw_taproot_address(pubkey):
+ return encode_segwit_address("bcrt", 1, pubkey)
+
class WalletTaprootTest(BitcoinTestFramework):
"""Test generation and spending of P2TR address outputs."""
@@ -218,21 +221,37 @@ class WalletTaprootTest(BitcoinTestFramework):
args = []
for j in range(len(keys)):
args.append(keys[j]['pubs'][i])
- return compute_taproot_address(*treefn(*args))
+ tree = treefn(*args)
+ if isinstance(tree, tuple):
+ return compute_taproot_address(*tree)
+ if isinstance(tree, bytes):
+ return compute_raw_taproot_address(tree)
+ assert False
def do_test_addr(self, comment, pattern, privmap, treefn, keys):
self.log.info("Testing %s address derivation" % comment)
+
+ # Create wallets
+ wallet_uuid = uuid.uuid4().hex
+ self.nodes[0].createwallet(wallet_name=f"privs_tr_enabled_{wallet_uuid}", descriptors=True, blank=True)
+ self.nodes[0].createwallet(wallet_name=f"pubs_tr_enabled_{wallet_uuid}", descriptors=True, blank=True, disable_private_keys=True)
+ self.nodes[0].createwallet(wallet_name=f"addr_gen_{wallet_uuid}", descriptors=True, disable_private_keys=True, blank=True)
+ privs_tr_enabled = self.nodes[0].get_wallet_rpc(f"privs_tr_enabled_{wallet_uuid}")
+ pubs_tr_enabled = self.nodes[0].get_wallet_rpc(f"pubs_tr_enabled_{wallet_uuid}")
+ addr_gen = self.nodes[0].get_wallet_rpc(f"addr_gen_{wallet_uuid}")
+
desc = self.make_desc(pattern, privmap, keys, False)
desc_pub = self.make_desc(pattern, privmap, keys, True)
assert_equal(self.nodes[0].getdescriptorinfo(desc)['descriptor'], desc_pub)
- result = self.addr_gen.importdescriptors([{"desc": desc_pub, "active": True, "timestamp": "now"}])
+ result = addr_gen.importdescriptors([{"desc": desc_pub, "active": True, "timestamp": "now"}])
assert(result[0]['success'])
+ address_type = "bech32m" if "tr" in pattern else "bech32"
for i in range(4):
- addr_g = self.addr_gen.getnewaddress(address_type='bech32m')
+ addr_g = addr_gen.getnewaddress(address_type=address_type)
if treefn is not None:
addr_r = self.make_addr(treefn, keys, i)
assert_equal(addr_g, addr_r)
- desc_a = self.addr_gen.getaddressinfo(addr_g)['desc']
+ desc_a = addr_gen.getaddressinfo(addr_g)['desc']
if desc.startswith("tr("):
assert desc_a.startswith("tr(")
rederive = self.nodes[1].deriveaddresses(desc_a)
@@ -240,25 +259,37 @@ class WalletTaprootTest(BitcoinTestFramework):
assert_equal(rederive[0], addr_g)
# tr descriptors can be imported
- result = self.privs_tr_enabled.importdescriptors([{"desc": desc, "timestamp": "now"}])
+ result = privs_tr_enabled.importdescriptors([{"desc": desc, "timestamp": "now"}])
assert(result[0]["success"])
- result = self.pubs_tr_enabled.importdescriptors([{"desc": desc_pub, "timestamp": "now"}])
+ result = pubs_tr_enabled.importdescriptors([{"desc": desc_pub, "timestamp": "now"}])
assert(result[0]["success"])
+ # Cleanup
+ privs_tr_enabled.unloadwallet()
+ pubs_tr_enabled.unloadwallet()
+ addr_gen.unloadwallet()
+
def do_test_sendtoaddress(self, comment, pattern, privmap, treefn, keys_pay, keys_change):
self.log.info("Testing %s through sendtoaddress" % comment)
+
+ # Create wallets
+ wallet_uuid = uuid.uuid4().hex
+ self.nodes[0].createwallet(wallet_name=f"rpc_online_{wallet_uuid}", descriptors=True, blank=True)
+ rpc_online = self.nodes[0].get_wallet_rpc(f"rpc_online_{wallet_uuid}")
+
desc_pay = self.make_desc(pattern, privmap, keys_pay)
desc_change = self.make_desc(pattern, privmap, keys_change)
desc_pay_pub = self.make_desc(pattern, privmap, keys_pay, True)
desc_change_pub = self.make_desc(pattern, privmap, keys_change, True)
assert_equal(self.nodes[0].getdescriptorinfo(desc_pay)['descriptor'], desc_pay_pub)
assert_equal(self.nodes[0].getdescriptorinfo(desc_change)['descriptor'], desc_change_pub)
- result = self.rpc_online.importdescriptors([{"desc": desc_pay, "active": True, "timestamp": "now"}])
+ result = rpc_online.importdescriptors([{"desc": desc_pay, "active": True, "timestamp": "now"}])
assert(result[0]['success'])
- result = self.rpc_online.importdescriptors([{"desc": desc_change, "active": True, "timestamp": "now", "internal": True}])
+ result = rpc_online.importdescriptors([{"desc": desc_change, "active": True, "timestamp": "now", "internal": True}])
assert(result[0]['success'])
+ address_type = "bech32m" if "tr" in pattern else "bech32"
for i in range(4):
- addr_g = self.rpc_online.getnewaddress(address_type='bech32m')
+ addr_g = rpc_online.getnewaddress(address_type=address_type)
if treefn is not None:
addr_r = self.make_addr(treefn, keys_pay, i)
assert_equal(addr_g, addr_r)
@@ -266,31 +297,51 @@ class WalletTaprootTest(BitcoinTestFramework):
to_amnt = random.randrange(1000000, boring_balance)
self.boring.sendtoaddress(address=addr_g, amount=Decimal(to_amnt) / 100000000, subtractfeefromamount=True)
self.generatetoaddress(self.nodes[0], 1, self.boring.getnewaddress(), sync_fun=self.no_op)
- test_balance = int(self.rpc_online.getbalance() * 100000000)
+ test_balance = int(rpc_online.getbalance() * 100000000)
ret_amnt = random.randrange(100000, test_balance)
# Increase fee_rate to compensate for the wallet's inability to estimate fees for script path spends.
- res = self.rpc_online.sendtoaddress(address=self.boring.getnewaddress(), amount=Decimal(ret_amnt) / 100000000, subtractfeefromamount=True, fee_rate=200)
+ res = rpc_online.sendtoaddress(address=self.boring.getnewaddress(), amount=Decimal(ret_amnt) / 100000000, subtractfeefromamount=True, fee_rate=200)
self.generatetoaddress(self.nodes[0], 1, self.boring.getnewaddress(), sync_fun=self.no_op)
- assert(self.rpc_online.gettransaction(res)["confirmations"] > 0)
+ assert(rpc_online.gettransaction(res)["confirmations"] > 0)
+
+ # Cleanup
+ txid = rpc_online.sendall(recipients=[self.boring.getnewaddress()])["txid"]
+ self.generatetoaddress(self.nodes[0], 1, self.boring.getnewaddress(), sync_fun=self.no_op)
+ assert(rpc_online.gettransaction(txid)["confirmations"] > 0)
+ rpc_online.unloadwallet()
def do_test_psbt(self, comment, pattern, privmap, treefn, keys_pay, keys_change):
self.log.info("Testing %s through PSBT" % comment)
+
+ # Create wallets
+ wallet_uuid = uuid.uuid4().hex
+ self.nodes[0].createwallet(wallet_name=f"psbt_online_{wallet_uuid}", descriptors=True, disable_private_keys=True, blank=True)
+ self.nodes[1].createwallet(wallet_name=f"psbt_offline_{wallet_uuid}", descriptors=True, blank=True)
+ self.nodes[1].createwallet(f"key_only_wallet_{wallet_uuid}", descriptors=True, blank=True)
+ psbt_online = self.nodes[0].get_wallet_rpc(f"psbt_online_{wallet_uuid}")
+ psbt_offline = self.nodes[1].get_wallet_rpc(f"psbt_offline_{wallet_uuid}")
+ key_only_wallet = self.nodes[1].get_wallet_rpc(f"key_only_wallet_{wallet_uuid}")
+
desc_pay = self.make_desc(pattern, privmap, keys_pay, False)
desc_change = self.make_desc(pattern, privmap, keys_change, False)
desc_pay_pub = self.make_desc(pattern, privmap, keys_pay, True)
desc_change_pub = self.make_desc(pattern, privmap, keys_change, True)
assert_equal(self.nodes[0].getdescriptorinfo(desc_pay)['descriptor'], desc_pay_pub)
assert_equal(self.nodes[0].getdescriptorinfo(desc_change)['descriptor'], desc_change_pub)
- result = self.psbt_online.importdescriptors([{"desc": desc_pay_pub, "active": True, "timestamp": "now"}])
+ result = psbt_online.importdescriptors([{"desc": desc_pay_pub, "active": True, "timestamp": "now"}])
assert(result[0]['success'])
- result = self.psbt_online.importdescriptors([{"desc": desc_change_pub, "active": True, "timestamp": "now", "internal": True}])
+ result = psbt_online.importdescriptors([{"desc": desc_change_pub, "active": True, "timestamp": "now", "internal": True}])
assert(result[0]['success'])
- result = self.psbt_offline.importdescriptors([{"desc": desc_pay, "active": True, "timestamp": "now"}])
+ result = psbt_offline.importdescriptors([{"desc": desc_pay, "active": True, "timestamp": "now"}])
assert(result[0]['success'])
- result = self.psbt_offline.importdescriptors([{"desc": desc_change, "active": True, "timestamp": "now", "internal": True}])
+ result = psbt_offline.importdescriptors([{"desc": desc_change, "active": True, "timestamp": "now", "internal": True}])
assert(result[0]['success'])
+ for key in keys_pay + keys_change:
+ result = key_only_wallet.importdescriptors([{"desc": descsum_create(f"wpkh({key['xprv']}/*)"), "timestamp":"now"}])
+ assert(result[0]["success"])
+ address_type = "bech32m" if "tr" in pattern else "bech32"
for i in range(4):
- addr_g = self.psbt_online.getnewaddress(address_type='bech32m')
+ addr_g = psbt_online.getnewaddress(address_type=address_type)
if treefn is not None:
addr_r = self.make_addr(treefn, keys_pay, i)
assert_equal(addr_g, addr_r)
@@ -298,16 +349,43 @@ class WalletTaprootTest(BitcoinTestFramework):
to_amnt = random.randrange(1000000, boring_balance)
self.boring.sendtoaddress(address=addr_g, amount=Decimal(to_amnt) / 100000000, subtractfeefromamount=True)
self.generatetoaddress(self.nodes[0], 1, self.boring.getnewaddress(), sync_fun=self.no_op)
- test_balance = int(self.psbt_online.getbalance() * 100000000)
+ test_balance = int(psbt_online.getbalance() * 100000000)
ret_amnt = random.randrange(100000, test_balance)
# Increase fee_rate to compensate for the wallet's inability to estimate fees for script path spends.
- psbt = self.psbt_online.walletcreatefundedpsbt([], [{self.boring.getnewaddress(): Decimal(ret_amnt) / 100000000}], None, {"subtractFeeFromOutputs":[0], "fee_rate": 200})['psbt']
- res = self.psbt_offline.walletprocesspsbt(psbt)
- assert(res['complete'])
- rawtx = self.nodes[0].finalizepsbt(res['psbt'])['hex']
+ psbt = psbt_online.walletcreatefundedpsbt([], [{self.boring.getnewaddress(): Decimal(ret_amnt) / 100000000}], None, {"subtractFeeFromOutputs":[0], "fee_rate": 200, "change_type": address_type})['psbt']
+ res = psbt_offline.walletprocesspsbt(psbt=psbt, finalize=False)
+ for wallet in [psbt_offline, key_only_wallet]:
+ res = wallet.walletprocesspsbt(psbt=psbt, finalize=False)
+
+ decoded = wallet.decodepsbt(res["psbt"])
+ if pattern.startswith("tr("):
+ for psbtin in decoded["inputs"]:
+ assert "non_witness_utxo" not in psbtin
+ assert "witness_utxo" in psbtin
+ assert "taproot_internal_key" in psbtin
+ assert "taproot_bip32_derivs" in psbtin
+ assert "taproot_key_path_sig" in psbtin or "taproot_script_path_sigs" in psbtin
+ if "taproot_script_path_sigs" in psbtin:
+ assert "taproot_merkle_root" in psbtin
+ assert "taproot_scripts" in psbtin
+
+ rawtx = self.nodes[0].finalizepsbt(res['psbt'])['hex']
+ res = self.nodes[0].testmempoolaccept([rawtx])
+ assert res[0]["allowed"]
+
txid = self.nodes[0].sendrawtransaction(rawtx)
self.generatetoaddress(self.nodes[0], 1, self.boring.getnewaddress(), sync_fun=self.no_op)
- assert(self.psbt_online.gettransaction(txid)['confirmations'] > 0)
+ assert(psbt_online.gettransaction(txid)['confirmations'] > 0)
+
+ # Cleanup
+ psbt = psbt_online.sendall(recipients=[self.boring.getnewaddress()], options={"psbt": True})["psbt"]
+ res = psbt_offline.walletprocesspsbt(psbt=psbt, finalize=False)
+ rawtx = self.nodes[0].finalizepsbt(res['psbt'])['hex']
+ txid = self.nodes[0].sendrawtransaction(rawtx)
+ self.generatetoaddress(self.nodes[0], 1, self.boring.getnewaddress(), sync_fun=self.no_op)
+ assert(psbt_online.gettransaction(txid)['confirmations'] > 0)
+ psbt_online.unloadwallet()
+ psbt_offline.unloadwallet()
def do_test(self, comment, pattern, privmap, treefn):
nkeys = len(privmap)
@@ -317,21 +395,8 @@ class WalletTaprootTest(BitcoinTestFramework):
self.do_test_psbt(comment, pattern, privmap, treefn, keys[2*nkeys:3*nkeys], keys[3*nkeys:4*nkeys])
def run_test(self):
- self.log.info("Creating wallets...")
- self.nodes[0].createwallet(wallet_name="privs_tr_enabled", descriptors=True, blank=True)
- self.privs_tr_enabled = self.nodes[0].get_wallet_rpc("privs_tr_enabled")
- self.nodes[0].createwallet(wallet_name="pubs_tr_enabled", descriptors=True, blank=True, disable_private_keys=True)
- self.pubs_tr_enabled = self.nodes[0].get_wallet_rpc("pubs_tr_enabled")
self.nodes[0].createwallet(wallet_name="boring")
- self.nodes[0].createwallet(wallet_name="addr_gen", descriptors=True, disable_private_keys=True, blank=True)
- self.nodes[0].createwallet(wallet_name="rpc_online", descriptors=True, blank=True)
- self.nodes[0].createwallet(wallet_name="psbt_online", descriptors=True, disable_private_keys=True, blank=True)
- self.nodes[1].createwallet(wallet_name="psbt_offline", descriptors=True, blank=True)
self.boring = self.nodes[0].get_wallet_rpc("boring")
- self.addr_gen = self.nodes[0].get_wallet_rpc("addr_gen")
- self.rpc_online = self.nodes[0].get_wallet_rpc("rpc_online")
- self.psbt_online = self.nodes[0].get_wallet_rpc("psbt_online")
- self.psbt_offline = self.nodes[1].get_wallet_rpc("psbt_offline")
self.log.info("Mining blocks...")
gen_addr = self.boring.getnewaddress()
@@ -434,20 +499,12 @@ class WalletTaprootTest(BitcoinTestFramework):
[True, False],
lambda k1, k2: (key(k2), [multi_a(1, ([H_POINT] * rnd_pos) + [k1] + ([H_POINT] * (MAX_PUBKEYS_PER_MULTI_A - 1 - rnd_pos)))])
)
-
- self.log.info("Sending everything back...")
-
- txid = self.rpc_online.sendall(recipients=[self.boring.getnewaddress()])["txid"]
- self.generatetoaddress(self.nodes[0], 1, self.boring.getnewaddress(), sync_fun=self.no_op)
- assert(self.rpc_online.gettransaction(txid)["confirmations"] > 0)
-
- psbt = self.psbt_online.sendall(recipients=[self.boring.getnewaddress()], options={"psbt": True})["psbt"]
- res = self.psbt_offline.walletprocesspsbt(psbt)
- assert(res['complete'])
- rawtx = self.nodes[0].finalizepsbt(res['psbt'])['hex']
- txid = self.nodes[0].sendrawtransaction(rawtx)
- self.generatetoaddress(self.nodes[0], 1, self.boring.getnewaddress(), sync_fun=self.no_op)
- assert(self.psbt_online.gettransaction(txid)['confirmations'] > 0)
+ self.do_test(
+ "rawtr(XPRV)",
+ "rawtr($1/*)",
+ [True],
+ lambda k1: key(k1)
+ )
if __name__ == '__main__':
WalletTaprootTest().main()
diff --git a/test/functional/wallet_transactiontime_rescan.py b/test/functional/wallet_transactiontime_rescan.py
index 21941084a3..9caa1fa3d0 100755
--- a/test/functional/wallet_transactiontime_rescan.py
+++ b/test/functional/wallet_transactiontime_rescan.py
@@ -11,6 +11,7 @@ from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
+ assert_raises_rpc_error,
set_node_times,
)
@@ -158,5 +159,11 @@ class TransactionTimeRescanTest(BitcoinTestFramework):
assert_equal(tx['time'], cur_time + ten_days + ten_days + ten_days)
+ self.log.info('Test handling of invalid parameters for rescanblockchain')
+ assert_raises_rpc_error(-8, "Invalid start_height", restorewo_wallet.rescanblockchain, -1, 10)
+ assert_raises_rpc_error(-8, "Invalid stop_height", restorewo_wallet.rescanblockchain, 1, -1)
+ assert_raises_rpc_error(-8, "stop_height must be greater than start_height", restorewo_wallet.rescanblockchain, 20, 10)
+
+
if __name__ == '__main__':
TransactionTimeRescanTest().main()
diff --git a/test/get_previous_releases.py b/test/get_previous_releases.py
index 7b7cfbfef5..c983dce619 100755
--- a/test/get_previous_releases.py
+++ b/test/get_previous_releases.py
@@ -20,66 +20,66 @@ import sys
import hashlib
SHA256_SUMS = {
- "0e2819135366f150d9906e294b61dff58fd1996ebd26c2f8e979d6c0b7a79580": "bitcoin-0.14.3-aarch64-linux-gnu.tar.gz",
- "d86fc90824a85c38b25c8488115178d5785dbc975f5ff674f9f5716bc8ad6e65": "bitcoin-0.14.3-arm-linux-gnueabihf.tar.gz",
- "1b0a7408c050e3d09a8be8e21e183ef7ee570385dc41216698cc3ab392a484e7": "bitcoin-0.14.3-osx64.tar.gz",
- "706e0472dbc933ed2757650d54cbcd780fd3829ebf8f609b32780c7eedebdbc9": "bitcoin-0.14.3-x86_64-linux-gnu.tar.gz",
+ "0e2819135366f150d9906e294b61dff58fd1996ebd26c2f8e979d6c0b7a79580": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-aarch64-linux-gnu.tar.gz"},
+ "d86fc90824a85c38b25c8488115178d5785dbc975f5ff674f9f5716bc8ad6e65": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-arm-linux-gnueabihf.tar.gz"},
+ "1b0a7408c050e3d09a8be8e21e183ef7ee570385dc41216698cc3ab392a484e7": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-osx64.tar.gz"},
+ "706e0472dbc933ed2757650d54cbcd780fd3829ebf8f609b32780c7eedebdbc9": {"tag": "v0.14.3", "tarball": "bitcoin-0.14.3-x86_64-linux-gnu.tar.gz"},
#
- "d40f18b4e43c6e6370ef7db9131f584fbb137276ec2e3dba67a4b267f81cb644": "bitcoin-0.15.2-aarch64-linux-gnu.tar.gz",
- "54fb877a148a6ad189a1e1ab1ff8b11181e58ff2aaf430da55b3fd46ae549a6b": "bitcoin-0.15.2-arm-linux-gnueabihf.tar.gz",
- "87e9340ff3d382d543b2b69112376077f0c8b4f7450d372e83b68f5a1e22b2df": "bitcoin-0.15.2-osx64.tar.gz",
- "566be44190fd76daa01f13d428939dadfb8e3daacefc8fa17f433cad28f73bd5": "bitcoin-0.15.2-x86_64-linux-gnu.tar.gz",
+ "d40f18b4e43c6e6370ef7db9131f584fbb137276ec2e3dba67a4b267f81cb644": {"tag": "v0.15.2", "tarball": "bitcoin-0.15.2-aarch64-linux-gnu.tar.gz"},
+ "54fb877a148a6ad189a1e1ab1ff8b11181e58ff2aaf430da55b3fd46ae549a6b": {"tag": "v0.15.2", "tarball": "bitcoin-0.15.2-arm-linux-gnueabihf.tar.gz"},
+ "87e9340ff3d382d543b2b69112376077f0c8b4f7450d372e83b68f5a1e22b2df": {"tag": "v0.15.2", "tarball": "bitcoin-0.15.2-osx64.tar.gz"},
+ "566be44190fd76daa01f13d428939dadfb8e3daacefc8fa17f433cad28f73bd5": {"tag": "v0.15.2", "tarball": "bitcoin-0.15.2-x86_64-linux-gnu.tar.gz"},
#
- "0768c6c15caffbaca6524824c9563b42c24f70633c681c2744649158aa3fd484": "bitcoin-0.16.3-aarch64-linux-gnu.tar.gz",
- "fb2818069854a6ad20ea03b28b55dbd35d8b1f7d453e90b83eace5d0098a2a87": "bitcoin-0.16.3-arm-linux-gnueabihf.tar.gz",
- "78c3bff3b619a19aed575961ea43cc9e142959218835cf51aede7f0b764fc25d": "bitcoin-0.16.3-osx64.tar.gz",
- "5d422a9d544742bc0df12427383f9c2517433ce7b58cf672b9a9b17c2ef51e4f": "bitcoin-0.16.3-x86_64-linux-gnu.tar.gz",
+ "0768c6c15caffbaca6524824c9563b42c24f70633c681c2744649158aa3fd484": {"tag": "v0.16.3", "tarball": "bitcoin-0.16.3-aarch64-linux-gnu.tar.gz"},
+ "fb2818069854a6ad20ea03b28b55dbd35d8b1f7d453e90b83eace5d0098a2a87": {"tag": "v0.16.3", "tarball": "bitcoin-0.16.3-arm-linux-gnueabihf.tar.gz"},
+ "78c3bff3b619a19aed575961ea43cc9e142959218835cf51aede7f0b764fc25d": {"tag": "v0.16.3", "tarball": "bitcoin-0.16.3-osx64.tar.gz"},
+ "5d422a9d544742bc0df12427383f9c2517433ce7b58cf672b9a9b17c2ef51e4f": {"tag": "v0.16.3", "tarball": "bitcoin-0.16.3-x86_64-linux-gnu.tar.gz"},
#
- "5a6b35d1a348a402f2d2d6ab5aed653a1a1f13bc63aaaf51605e3501b0733b7a": "bitcoin-0.17.2-aarch64-linux-gnu.tar.gz",
- "d1913a5d19c8e8da4a67d1bd5205d03c8614dfd2e02bba2fe3087476643a729e": "bitcoin-0.17.2-arm-linux-gnueabihf.tar.gz",
- "a783ba20706dbfd5b47fbedf42165fce70fbbc7d78003305d964f6b3da14887f": "bitcoin-0.17.2-osx64.tar.gz",
- "943f9362b9f11130177839116f48f809d83478b4c28591d486ee9a7e35179da6": "bitcoin-0.17.2-x86_64-linux-gnu.tar.gz",
+ "5a6b35d1a348a402f2d2d6ab5aed653a1a1f13bc63aaaf51605e3501b0733b7a": {"tag": "v0.17.2", "tarball": "bitcoin-0.17.2-aarch64-linux-gnu.tar.gz"},
+ "d1913a5d19c8e8da4a67d1bd5205d03c8614dfd2e02bba2fe3087476643a729e": {"tag": "v0.17.2", "tarball": "bitcoin-0.17.2-arm-linux-gnueabihf.tar.gz"},
+ "a783ba20706dbfd5b47fbedf42165fce70fbbc7d78003305d964f6b3da14887f": {"tag": "v0.17.2", "tarball": "bitcoin-0.17.2-osx64.tar.gz"},
+ "943f9362b9f11130177839116f48f809d83478b4c28591d486ee9a7e35179da6": {"tag": "v0.17.2", "tarball": "bitcoin-0.17.2-x86_64-linux-gnu.tar.gz"},
#
- "88f343af72803b851c7da13874cc5525026b0b55e63e1b5e1298390c4688adc6": "bitcoin-0.18.1-aarch64-linux-gnu.tar.gz",
- "cc7d483e4b20c5dabd4dcaf304965214cf4934bcc029ca99cbc9af00d3771a1f": "bitcoin-0.18.1-arm-linux-gnueabihf.tar.gz",
- "b7bbcee7a7540f711b171d6981f939ca8482005fde22689bc016596d80548bb1": "bitcoin-0.18.1-osx64.tar.gz",
- "425ee5ec631ae8da71ebc1c3f5c0269c627cf459379b9b030f047107a28e3ef8": "bitcoin-0.18.1-riscv64-linux-gnu.tar.gz",
- "600d1db5e751fa85903e935a01a74f5cc57e1e7473c15fd3e17ed21e202cfe5a": "bitcoin-0.18.1-x86_64-linux-gnu.tar.gz",
+ "88f343af72803b851c7da13874cc5525026b0b55e63e1b5e1298390c4688adc6": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-aarch64-linux-gnu.tar.gz"},
+ "cc7d483e4b20c5dabd4dcaf304965214cf4934bcc029ca99cbc9af00d3771a1f": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-arm-linux-gnueabihf.tar.gz"},
+ "b7bbcee7a7540f711b171d6981f939ca8482005fde22689bc016596d80548bb1": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-osx64.tar.gz"},
+ "425ee5ec631ae8da71ebc1c3f5c0269c627cf459379b9b030f047107a28e3ef8": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-riscv64-linux-gnu.tar.gz"},
+ "600d1db5e751fa85903e935a01a74f5cc57e1e7473c15fd3e17ed21e202cfe5a": {"tag": "v0.18.1", "tarball": "bitcoin-0.18.1-x86_64-linux-gnu.tar.gz"},
#
- "3a80431717842672df682bdb619e66523b59541483297772a7969413be3502ff": "bitcoin-0.19.1-aarch64-linux-gnu.tar.gz",
- "657f28213823d240dd3324d14829702f9ad6f0710f8bdd1c379cb3c447197f48": "bitcoin-0.19.1-arm-linux-gnueabihf.tar.gz",
- "1ae1b87de26487075cd2fd22e0d4ead87d969bd55c44f2f1d873ecdc6147ebb3": "bitcoin-0.19.1-osx64.tar.gz",
- "aa7a9563b48aa79252c8e7b6a41c07a5441bd9f14c5e4562cc72720ea6cb0ee5": "bitcoin-0.19.1-riscv64-linux-gnu.tar.gz",
- "5fcac9416e486d4960e1a946145566350ca670f9aaba99de6542080851122e4c": "bitcoin-0.19.1-x86_64-linux-gnu.tar.gz",
+ "3a80431717842672df682bdb619e66523b59541483297772a7969413be3502ff": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-aarch64-linux-gnu.tar.gz"},
+ "657f28213823d240dd3324d14829702f9ad6f0710f8bdd1c379cb3c447197f48": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-arm-linux-gnueabihf.tar.gz"},
+ "1ae1b87de26487075cd2fd22e0d4ead87d969bd55c44f2f1d873ecdc6147ebb3": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-osx64.tar.gz"},
+ "aa7a9563b48aa79252c8e7b6a41c07a5441bd9f14c5e4562cc72720ea6cb0ee5": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-riscv64-linux-gnu.tar.gz"},
+ "5fcac9416e486d4960e1a946145566350ca670f9aaba99de6542080851122e4c": {"tag": "v0.19.1", "tarball": "bitcoin-0.19.1-x86_64-linux-gnu.tar.gz"},
#
- "60c93e3462c303eb080be7cf623f1a7684b37fd47a018ad3848bc23e13c84e1c": "bitcoin-0.20.1-aarch64-linux-gnu.tar.gz",
- "55b577e0fb306fb429d4be6c9316607753e8543e5946b542d75d876a2f08654c": "bitcoin-0.20.1-arm-linux-gnueabihf.tar.gz",
- "b9024dde373ea7dad707363e07ec7e265383204127539ae0c234bff3a61da0d1": "bitcoin-0.20.1-osx64.tar.gz",
- "fa71cb52ee5e0459cbf5248cdec72df27995840c796f58b304607a1ed4c165af": "bitcoin-0.20.1-riscv64-linux-gnu.tar.gz",
- "376194f06596ecfa40331167c39bc70c355f960280bd2a645fdbf18f66527397": "bitcoin-0.20.1-x86_64-linux-gnu.tar.gz",
+ "60c93e3462c303eb080be7cf623f1a7684b37fd47a018ad3848bc23e13c84e1c": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-aarch64-linux-gnu.tar.gz"},
+ "55b577e0fb306fb429d4be6c9316607753e8543e5946b542d75d876a2f08654c": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-arm-linux-gnueabihf.tar.gz"},
+ "b9024dde373ea7dad707363e07ec7e265383204127539ae0c234bff3a61da0d1": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-osx64.tar.gz"},
+ "fa71cb52ee5e0459cbf5248cdec72df27995840c796f58b304607a1ed4c165af": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-riscv64-linux-gnu.tar.gz"},
+ "376194f06596ecfa40331167c39bc70c355f960280bd2a645fdbf18f66527397": {"tag": "v0.20.1", "tarball": "bitcoin-0.20.1-x86_64-linux-gnu.tar.gz"},
- "43416854330914992bbba2d0e9adf2a6fff4130be9af8ae2ef1186e743d9a3fe": "bitcoin-0.21.0-aarch64-linux-gnu.tar.gz",
- "f028af308eda45a3c4c90f9332f96b075bf21e3495c945ebce48597151808176": "bitcoin-0.21.0-arm-linux-gnueabihf.tar.gz",
- "695fb624fa6423f5da4f443b60763dd1d77488bfe5ef63760904a7b54e91298d": "bitcoin-0.21.0-osx64.tar.gz",
- "f8b2adfeae021a672effbc7bd40d5c48d6b94e53b2dd660f787340bf1a52e4e9": "bitcoin-0.21.0-riscv64-linux-gnu.tar.gz",
- "da7766775e3f9c98d7a9145429f2be8297c2672fe5b118fd3dc2411fb48e0032": "bitcoin-0.21.0-x86_64-linux-gnu.tar.gz",
+ "43416854330914992bbba2d0e9adf2a6fff4130be9af8ae2ef1186e743d9a3fe": {"tag": "v0.21.0", "tarball": "bitcoin-0.21.0-aarch64-linux-gnu.tar.gz"},
+ "f028af308eda45a3c4c90f9332f96b075bf21e3495c945ebce48597151808176": {"tag": "v0.21.0", "tarball": "bitcoin-0.21.0-arm-linux-gnueabihf.tar.gz"},
+ "695fb624fa6423f5da4f443b60763dd1d77488bfe5ef63760904a7b54e91298d": {"tag": "v0.21.0", "tarball": "bitcoin-0.21.0-osx64.tar.gz"},
+ "f8b2adfeae021a672effbc7bd40d5c48d6b94e53b2dd660f787340bf1a52e4e9": {"tag": "v0.21.0", "tarball": "bitcoin-0.21.0-riscv64-linux-gnu.tar.gz"},
+ "da7766775e3f9c98d7a9145429f2be8297c2672fe5b118fd3dc2411fb48e0032": {"tag": "v0.21.0", "tarball": "bitcoin-0.21.0-x86_64-linux-gnu.tar.gz"},
- "ac718fed08570a81b3587587872ad85a25173afa5f9fbbd0c03ba4d1714cfa3e": "bitcoin-22.0-aarch64-linux-gnu.tar.gz",
- "b8713c6c5f03f5258b54e9f436e2ed6d85449aa24c2c9972f91963d413e86311": "bitcoin-22.0-arm-linux-gnueabihf.tar.gz",
- "2744d199c3343b2d94faffdfb2c94d75a630ba27301a70e47b0ad30a7e0155e9": "bitcoin-22.0-osx64.tar.gz",
- "2cca5f99007d060aca9d8c7cbd035dfe2f040dd8200b210ce32cdf858479f70d": "bitcoin-22.0-powerpc64-linux-gnu.tar.gz",
- "91b1e012975c5a363b5b5fcc81b5b7495e86ff703ec8262d4b9afcfec633c30d": "bitcoin-22.0-powerpc64le-linux-gnu.tar.gz",
- "9cc3a62c469fe57e11485fdd32c916f10ce7a2899299855a2e479256ff49ff3c": "bitcoin-22.0-riscv64-linux-gnu.tar.gz",
- "59ebd25dd82a51638b7a6bb914586201e67db67b919b2a1ff08925a7936d1b16": "bitcoin-22.0-x86_64-linux-gnu.tar.gz",
+ "ac718fed08570a81b3587587872ad85a25173afa5f9fbbd0c03ba4d1714cfa3e": {"tag": "v22.0", "tarball": "bitcoin-22.0-aarch64-linux-gnu.tar.gz"},
+ "b8713c6c5f03f5258b54e9f436e2ed6d85449aa24c2c9972f91963d413e86311": {"tag": "v22.0", "tarball": "bitcoin-22.0-arm-linux-gnueabihf.tar.gz"},
+ "2744d199c3343b2d94faffdfb2c94d75a630ba27301a70e47b0ad30a7e0155e9": {"tag": "v22.0", "tarball": "bitcoin-22.0-osx64.tar.gz"},
+ "2cca5f99007d060aca9d8c7cbd035dfe2f040dd8200b210ce32cdf858479f70d": {"tag": "v22.0", "tarball": "bitcoin-22.0-powerpc64-linux-gnu.tar.gz"},
+ "91b1e012975c5a363b5b5fcc81b5b7495e86ff703ec8262d4b9afcfec633c30d": {"tag": "v22.0", "tarball": "bitcoin-22.0-powerpc64le-linux-gnu.tar.gz"},
+ "9cc3a62c469fe57e11485fdd32c916f10ce7a2899299855a2e479256ff49ff3c": {"tag": "v22.0", "tarball": "bitcoin-22.0-riscv64-linux-gnu.tar.gz"},
+ "59ebd25dd82a51638b7a6bb914586201e67db67b919b2a1ff08925a7936d1b16": {"tag": "v22.0", "tarball": "bitcoin-22.0-x86_64-linux-gnu.tar.gz"},
- "06f4c78271a77752ba5990d60d81b1751507f77efda1e5981b4e92fd4d9969fb": "bitcoin-23.0-aarch64-linux-gnu.tar.gz",
- "952c574366aff76f6d6ad1c9ee45a361d64fa04155e973e926dfe7e26f9703a3": "bitcoin-23.0-arm-linux-gnueabihf.tar.gz",
- "7c8bc63731aa872b7b334a8a7d96e33536ad77d49029bad179b09dca32cd77ac": "bitcoin-23.0-arm64-apple-darwin.tar.gz",
- "2caa5898399e415f61d9af80a366a3008e5856efa15aaff74b88acf429674c99": "bitcoin-23.0-powerpc64-linux-gnu.tar.gz",
- "217dd0469d0f4962d22818c368358575f6a0abcba8804807bb75325eb2f28b19": "bitcoin-23.0-powerpc64le-linux-gnu.tar.gz",
- "078f96b1e92895009c798ab827fb3fde5f6719eee886bd0c0e93acab18ea4865": "bitcoin-23.0-riscv64-linux-gnu.tar.gz",
- "c816780583009a9dad426dc0c183c89be9da98906e1e2c7ebae91041c1aaaaf3": "bitcoin-23.0-x86_64-apple-darwin.tar.gz",
- "2cca490c1f2842884a3c5b0606f179f9f937177da4eadd628e3f7fd7e25d26d0": "bitcoin-23.0-x86_64-linux-gnu.tar.gz",
+ "06f4c78271a77752ba5990d60d81b1751507f77efda1e5981b4e92fd4d9969fb": {"tag": "v23.0", "tarball": "bitcoin-23.0-aarch64-linux-gnu.tar.gz"},
+ "952c574366aff76f6d6ad1c9ee45a361d64fa04155e973e926dfe7e26f9703a3": {"tag": "v23.0", "tarball": "bitcoin-23.0-arm-linux-gnueabihf.tar.gz"},
+ "7c8bc63731aa872b7b334a8a7d96e33536ad77d49029bad179b09dca32cd77ac": {"tag": "v23.0", "tarball": "bitcoin-23.0-arm64-apple-darwin.tar.gz"},
+ "2caa5898399e415f61d9af80a366a3008e5856efa15aaff74b88acf429674c99": {"tag": "v23.0", "tarball": "bitcoin-23.0-powerpc64-linux-gnu.tar.gz"},
+ "217dd0469d0f4962d22818c368358575f6a0abcba8804807bb75325eb2f28b19": {"tag": "v23.0", "tarball": "bitcoin-23.0-powerpc64le-linux-gnu.tar.gz"},
+ "078f96b1e92895009c798ab827fb3fde5f6719eee886bd0c0e93acab18ea4865": {"tag": "v23.0", "tarball": "bitcoin-23.0-riscv64-linux-gnu.tar.gz"},
+ "c816780583009a9dad426dc0c183c89be9da98906e1e2c7ebae91041c1aaaaf3": {"tag": "v23.0", "tarball": "bitcoin-23.0-x86_64-apple-darwin.tar.gz"},
+ "2cca490c1f2842884a3c5b0606f179f9f937177da4eadd628e3f7fd7e25d26d0": {"tag": "v23.0", "tarball": "bitcoin-23.0-x86_64-linux-gnu.tar.gz"},
}
@@ -135,7 +135,7 @@ def download_binary(tag, args) -> int:
hasher.update(afile.read())
tarballHash = hasher.hexdigest()
- if tarballHash not in SHA256_SUMS or SHA256_SUMS[tarballHash] != tarball:
+ if tarballHash not in SHA256_SUMS or SHA256_SUMS[tarballHash]['tarball'] != tarball:
if tarball in SHA256_SUMS.values():
print("Checksum did not match")
return 1
@@ -260,7 +260,12 @@ if __name__ == '__main__':
help='download release binary.')
parser.add_argument('-t', '--target-dir', action='store',
help='target directory.', default='releases')
- parser.add_argument('tags', nargs='+',
- help="release tags. e.g.: v0.18.1 v0.20.0rc2")
+ parser.add_argument('tags', nargs='*', default=set(
+ [v['tag'] for v in SHA256_SUMS.values()]
+ ),
+ help='release tags. e.g.: v0.18.1 v0.20.0rc2 '
+ '(if not specified, the full list needed for'
+ 'backwards compatibility tests will be used)'
+ )
args = parser.parse_args()
sys.exit(main(args))
diff --git a/test/lint/lint-circular-dependencies.py b/test/lint/lint-circular-dependencies.py
index 5d157eb4b1..a0f17ac119 100755
--- a/test/lint/lint-circular-dependencies.py
+++ b/test/lint/lint-circular-dependencies.py
@@ -22,6 +22,10 @@ EXPECTED_CIRCULAR_DEPENDENCIES = (
"wallet/fees -> wallet/wallet -> wallet/fees",
"wallet/wallet -> wallet/walletdb -> wallet/wallet",
"kernel/coinstats -> validation -> kernel/coinstats",
+ "kernel/mempool_persist -> validation -> kernel/mempool_persist",
+
+ # Temporary, removed in followup https://github.com/bitcoin/bitcoin/pull/24230
+ "index/base -> node/context -> net_processing -> index/blockfilterindex -> index/base",
)
CODE_DIR = "src"
diff --git a/test/lint/lint-git-commit-check.py b/test/lint/lint-git-commit-check.py
index a1d03370e8..049104398a 100755
--- a/test/lint/lint-git-commit-check.py
+++ b/test/lint/lint-git-commit-check.py
@@ -46,6 +46,8 @@ def main():
commit_range = merge_base + "..HEAD"
else:
commit_range = os.getenv("COMMIT_RANGE")
+ if commit_range == "SKIP_EMPTY_NOT_A_PR":
+ sys.exit(0)
commit_hashes = check_output(["git", "log", commit_range, "--format=%H"], universal_newlines=True, encoding="utf8").splitlines()
diff --git a/test/lint/lint-includes.py b/test/lint/lint-includes.py
index afdca0d418..b3fa4b9303 100755
--- a/test/lint/lint-includes.py
+++ b/test/lint/lint-includes.py
@@ -21,8 +21,7 @@ EXCLUDED_DIRS = ["src/leveldb/",
"src/minisketch/",
]
-EXPECTED_BOOST_INCLUDES = ["boost/algorithm/string/replace.hpp",
- "boost/date_time/posix_time/posix_time.hpp",
+EXPECTED_BOOST_INCLUDES = ["boost/date_time/posix_time/posix_time.hpp",
"boost/multi_index/hashed_index.hpp",
"boost/multi_index/ordered_index.hpp",
"boost/multi_index/sequenced_index.hpp",
diff --git a/test/lint/lint-whitespace.py b/test/lint/lint-whitespace.py
index 3fb5b80013..72b7ebc394 100755
--- a/test/lint/lint-whitespace.py
+++ b/test/lint/lint-whitespace.py
@@ -97,6 +97,8 @@ def main():
commit_range = merge_base + "..HEAD"
else:
commit_range = os.getenv("COMMIT_RANGE")
+ if commit_range == "SKIP_EMPTY_NOT_A_PR":
+ sys.exit(0)
whitespace_selection = []
tab_selection = []
diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan
index 3acf575d07..d331991273 100644
--- a/test/sanitizer_suppressions/tsan
+++ b/test/sanitizer_suppressions/tsan
@@ -13,7 +13,7 @@ race:zmq::*
race:bitcoin-qt
# deadlock (TODO fix)
-deadlock:CChainState::ConnectTip
+deadlock:Chainstate::ConnectTip
# Intentional deadlock in tests
deadlock:sync_tests::potential_deadlock_detected
diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan
index e6cfe5f81a..67ef512895 100644
--- a/test/sanitizer_suppressions/ubsan
+++ b/test/sanitizer_suppressions/ubsan
@@ -1,10 +1,10 @@
# -fsanitize=undefined suppressions
# =================================
-# This would be `signed-integer-overflow:CTxMemPool::PrioritiseTransaction`,
+# The suppressions would be `sanitize-type:ClassName::MethodName`,
# however due to a bug in clang the symbolizer is disabled and thus no symbol
# names can be used.
# See https://github.com/google/sanitizers/issues/1364
-signed-integer-overflow:txmempool.cpp
+
# https://github.com/bitcoin/bitcoin/pull/21798#issuecomment-829180719
signed-integer-overflow:policy/feerate.cpp